1906 最长递增子序列问题

题解:

第一问是普通的DP,同时为后面做铺垫。

后面的在《线性规划与网络流24题》里说的要比我好,引用来:

第一问动态规划已经求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K。
1、把序列每位i拆成两个点<i.a>和<i.b>,从<i.a>到<i.b>连接一条容量为1的有向边。
2、建立附加源S和汇T,如果序列第i位有F[i]=K,从S到<i.a>连接一条容量为1的有向边。
3、如果F[i]=1,从<i.b>到T连接一条容量为1的有向边。
4、如果j>i且A[i] < A[j]且F[j]+1=F[i],从<i.b>到<j.a>连接一条容量为1的有向边。

求网络最大流,就是第二问的结果。把边(<1.a>,<1.b>)(<N.a>,<N.b>)(S,<1.a>)(<N.b>,T)这四条边的容量修改为无穷大,再求一次网络最大流,就是第三问结果。

另外本题还有费用流的做法,但应该不会比2ms还快吧(求喷)。

代码:

总时间耗费: 2ms 
总内存耗费: 364B

#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;const int maxn = 2000 + 10;
const int INF = 1e9 + 7;int n, m, s, t;
int a[maxn], f[maxn];struct Edge {int from, to, cap, flow;
};vector<Edge> edges;
vector<int> G[maxn];void AddEdge(int from, int to, int cap) {edges.push_back((Edge){from, to, cap, 0});edges.push_back((Edge){to, from, 0, 0});int sz = edges.size();G[from].push_back(sz-2);G[to].push_back(sz-1);
}bool vis[maxn];
int d[maxn];
bool BFS() {queue<int> Q;Q.push(s);memset(vis, 0, sizeof(vis));d[s] = 0;vis[s] = 1;while(!Q.empty()) {int u = Q.front(); Q.pop();for(int i = 0; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(!vis[e.to] && e.cap > e.flow) {vis[e.to] = 1;d[e.to] = d[u] + 1;Q.push(e.to);}}}return vis[t];
}int cur[maxn];int DFS(int u, int a) {if(a == 0 || u == t) return a;int f, flow = 0;for(int& i = cur[u]; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {flow += f;e.flow += f;a -= f;edges[G[u][i]^1].flow -= f;if(a == 0) break;}}return flow;
}void Maxflow() {if(m == 1) { cout << n << endl; return; }int flow = 0;while(BFS()) {memset(cur, 0, sizeof(cur));flow += DFS(s, INF);}cout << flow << endl;
}void init() {cin >> n;for(int i = 1; i <= n; i++) cin >> a[i];s = 0; t = n * 2 + 1;
}void DP() {f[n] = 1;for(int i = n; i >= 1; i--) {f[i] = 1;for(int j = n; j > i; j--) if(a[i] <= a[j]) //mistake2f[i] = max(f[i], f[j]+1);m = max(m, f[i]);}cout << m << endl;
}void init_1() {for(int i = n; i >= 1; i--) {AddEdge(i, i+n, 1);if(f[i] == m) AddEdge(s, i, 1);if(f[i] == 1) AddEdge(i+n, t, 1);for(int j = i+1; j <= n; j++)if(f[i] == f[j] + 1 && a[i] <= a[j]) AddEdge(i+n, j, 1); //mistake3}
}void init_2() {edges.clear();for(int i = s; i <= t; i++) G[i].clear();for(int i = n; i >= 1; i--) {int cap = (i == 1 || i == n) ? INF : 1;AddEdge(i, i+n, cap); if(f[i] == m) AddEdge(s, i, cap); if(f[i] == 1) AddEdge(i+n, t, cap); for(int j = n; j > i; j--)if(f[i] == f[j] + 1 && a[i] <= a[j]) AddEdge(i+n, j, 1); //mistake4}
}int main() {init();DP();init_1();Maxflow();init_2();Maxflow();return 0;
}

[codevs 1906] 最长递增子序列问题相关推荐

  1. 最长递增子序列的两种解法

    以LeetCode-300为例: O(n^2)解法: dp数组表示以i结尾的最长递增子序列的长度 class Solution { public:int lengthOfLIS(vector<i ...

  2. 最长递增子序列问题的求解

    一, 最长递增子序列问题的描述 设L=<a1,a2,-,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列Lin=<aK1,ak2,-,akm>,其中k1<k2 ...

  3. 编程之美2.16 最长递增子序列

          这道题目要求返回一个数字,这个数字代表一个数组中最长的递增子序列,当然,不要求这个序列是连续的,比如,有这样一个数组:{1, 3,5,7, 2, 9},那么这个数组的最长递增子序列就是5, ...

  4. 洛谷P2766-最长递增子序列问题

    chunlvxiong的博客 题目描述: 给定正整数序列x1,...,xn (1≤n≤500). 1.计算其最长递增子序列的长度s. 2.计算从给定的序列中最多可取出多少个长度为s的递增子序列. 3. ...

  5. 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

    最大子序列 最大子序列是要找出由数组成的一维数组中和最大的连续子序列.比如{5,-3,4,2}的最大子序列就是 {5,-3,4,2},它的和是8,达到最大:而 {5,-6,4,2}的最大子序列是{4, ...

  6. 拦截导弹(最长递增子序列)

    题目描述:某国为了防御敌国的导弹袭击,开发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹 ...

  7. Java输出数组中最长递增子序列的代码

    下面内容是关于Java输出数组中最长递增子序列的内容,希望对大伙有较大用途. package com.wzs;import java.util.ArrayList; import java.util. ...

  8. 动态规划(最长递增子序列)---最长递增子序列

    最长递增子序列 300. Longest Increasing Subsequence (Medium) 题目描述:   给定一个数组,找到它的最长递增子序列 思路分析:   动态规划思想,定义一个数 ...

  9. 112. Leetcode 673. 最长递增子序列的个数 (动态规划-子序列问题)

    步骤一.确定状态: 确定dp数组及下标含义 dp[i]表示以nums[i]结尾的数组最长递增子序列的长度, count数组, count[i]记 录以nums[i]结尾的数组,最长递增子序列的个数. ...

最新文章

  1. 2017《面向对象程序设计》寒假作业一
  2. cvGEMM()函数(矩阵通用乘法运算)
  3. Spring Boot异常
  4. Linux Oracle10g安装
  5. axure9 html文件使用ie打开图片无法显示_win7系统html文件如何打开 win7系统html文件打开方法【介绍】...
  6. c#将http调用返回额json中的有关中文的unicode转换为中文
  7. Python3 爬虫学习笔记 C07 【解析库 lxml】
  8. linux文件大小和目录,查看Linux目录和文件大小
  9. Django+xadmin 打造线上教育平台(二)-1(旧)
  10. 准备入行Web前端,又担心适不适合,怎么办?
  11. 最新消息:更多的Windows Azure Marketplace Content 和Hands On Lab
  12. Linux Socket之send()异步通信时:Broken pipe报错
  13. Linux 命令行快捷键
  14. DevExpress GridView 排序状态下新增行不参与排序
  15. 最新版本kindle安卓app导入mobi图书和设置自定义字体的方法2020.01.09
  16. 沉默的潜意识音频Creator软件
  17. Python 基于豆瓣电影的可视化分析系统
  18. 《用于预测蛋白质-配体结合亲和力的结构感知交互图神经网络》
  19. 苹果告诉你-想自己换电池延长iPhone寿命还是算了吧!
  20. 生活大爆炸之光速可变,光速可超

热门文章

  1. 致青春——谁的青春没有遗憾2018-01-05
  2. 3DSlicer25:Report an Error
  3. VTK修炼之道46:图形基本操作进阶_三角网格体积、表面积、测地距离、包围盒
  4. NorthWest University - Medical Engineering
  5. 一个基于xml的超级orm框架-世界是由懒人创造的。
  6. BUUCTF-Reverse:reverse3
  7. 【❗JS奇技淫巧❗】JavaScript:截取DataURL中的base64字符串
  8. Linux 网络诊断命令
  9. 树莓派学习 -- 无法扫描出树莓派IP
  10. PM2.5检测 -- PMS7003 串口测试