网络流与线性规划24题06最长递增子序列问题
2013-03-28 20:46
295 查看
问题描述:
给定正整数序列X1....... Xn 。
(1)计算其最长递增子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
(3)如果允许在取出的序列中多次使用X1和Xn,则从给定序列中最多可取出多少个长
度为s的递增子序列。
编程任务:
设计有效算法完成(1)(2)(3)提出的计算任务。
数据输入:
由文件input.txt提供输入数据。文件第1 行有1个正整数n,表示给定序列的长度。接
下来的1 行有n个正整数X1......Xn 。
结果输出:
程序运行结束时,将任务(1)(2)(3)的解答输出到文件output.txt中。第1 行是最长
递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出
的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。
输入示例:
4
3 6 2 5
输出示例
2
2
3
分析:
首先要说的是示例数据第三个不应该是3,先放着,到后面在谈。首先第一问是经典的LIS问题,即最长递增子序列,用DP很容易就解出来了,f(i)表示以i结尾的序列的最长递增子序列长度。状态转移方程是:f(i)=max{ f(j) | j<i,a[j]<a[i]}+1。这是一个O(n^2)的算法,有更快的O(nlogn),不过我没写,因为数据规模很小,O(n^2)够了。以后准备写一个整理算法的专栏,到时候会介绍。
然后,建立最大流模型,这个模型就是有节点容量的网络流模型,把每个点拆成入点和出点,连接出入点,边权为1表示每个点只能选择一次。创建源点和汇点,连接源点和每个f[i]=1的点,连接汇点和每个f[i]=s的点,然后对于每个两个点,如果f[i]+1=f[j],则连接i点和j点,边权为正无穷。然后求最大流就可。
第三问我感觉有点小漏洞,不知道是我想错了还是什么,就是把X1,Xn出入点边权正无穷,然后把源点和X1入点正无穷,如果f
=s,就把Xn出点和汇点连接边权正无穷,然后再求一次最大流。
可是这样有一个bug,如果f
=2,就会产生错误,因为从源点->X1->Xn->汇点边权都是正无穷。所以感觉题目出的很怪异,不过暂且就这么解吧,可能是我目前境界不够。所以如果复制了这个代码,运行出错,千万别怪我。
或者有哪位大牛能指出我的BUG,感激不尽。
代码:
给定正整数序列X1....... Xn 。
(1)计算其最长递增子序列的长度s。
(2)计算从给定的序列中最多可取出多少个长度为s的递增子序列。
(3)如果允许在取出的序列中多次使用X1和Xn,则从给定序列中最多可取出多少个长
度为s的递增子序列。
编程任务:
设计有效算法完成(1)(2)(3)提出的计算任务。
数据输入:
由文件input.txt提供输入数据。文件第1 行有1个正整数n,表示给定序列的长度。接
下来的1 行有n个正整数X1......Xn 。
结果输出:
程序运行结束时,将任务(1)(2)(3)的解答输出到文件output.txt中。第1 行是最长
递增子序列的长度s。第2行是可取出的长度为s 的递增子序列个数。第3行是允许在取出
的序列中多次使用x1和xn时可取出的长度为s 的递增子序列个数。
输入示例:
4
3 6 2 5
输出示例
2
2
3
分析:
首先要说的是示例数据第三个不应该是3,先放着,到后面在谈。首先第一问是经典的LIS问题,即最长递增子序列,用DP很容易就解出来了,f(i)表示以i结尾的序列的最长递增子序列长度。状态转移方程是:f(i)=max{ f(j) | j<i,a[j]<a[i]}+1。这是一个O(n^2)的算法,有更快的O(nlogn),不过我没写,因为数据规模很小,O(n^2)够了。以后准备写一个整理算法的专栏,到时候会介绍。
然后,建立最大流模型,这个模型就是有节点容量的网络流模型,把每个点拆成入点和出点,连接出入点,边权为1表示每个点只能选择一次。创建源点和汇点,连接源点和每个f[i]=1的点,连接汇点和每个f[i]=s的点,然后对于每个两个点,如果f[i]+1=f[j],则连接i点和j点,边权为正无穷。然后求最大流就可。
第三问我感觉有点小漏洞,不知道是我想错了还是什么,就是把X1,Xn出入点边权正无穷,然后把源点和X1入点正无穷,如果f
=s,就把Xn出点和汇点连接边权正无穷,然后再求一次最大流。
可是这样有一个bug,如果f
=2,就会产生错误,因为从源点->X1->Xn->汇点边权都是正无穷。所以感觉题目出的很怪异,不过暂且就这么解吧,可能是我目前境界不够。所以如果复制了这个代码,运行出错,千万别怪我。
或者有哪位大牛能指出我的BUG,感激不尽。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn = 660; const int INF = 1<<30; struct edge{ int from,to,cap,flow; edge(int a,int b,int c,int d):from(a),to(b),cap(c),flow(d) {} }; vector<int> g[maxn]; vector<edge> edges; int a[maxn]; int f[maxn]; bool visit[maxn]; int d[maxn]; int cur[maxn]; int t,s; 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 m=edges.size(); g[from].push_back(m-2); g[to].push_back(m-1); } void buildgraph(int n,int m) { s=0;t=2*n+1; for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++) if(f[i]+1==f[j]) addedge(i+n,j,INF);//连接的边权为无穷 addedge(i,i+n,1);//拆点为2个,权值为1,保证每个点只选一次 if(f[i]==1) addedge(s,i,1); if(f[i]==m) addedge(i+n,t,1); } } bool BFS() { memset(visit,false,sizeof(visit)); d[s]=0; queue<int> q; q.push(s); visit[s]=true; while(!q.empty()){ int x=q.front();q.pop(); for(int i=0;i<g[x].size();i++){ edge &e=edges[g[x][i]]; if(!visit[e.to]&&e.cap>e.flow){ visit[e.to]=true; d[e.to]=d[x]+1; q.push(e.to); } } } return visit[t]; } int DFS(int x,int a) { if(x==t||a==0) return a; int flow=0,f; for(int &i=cur[x];i<g[x].size();i++){ edge &e=edges[g[x][i]]; if(d[e.to]==d[x]+1&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){ flow+=f; a-=f; e.flow+=f; edges[g[x][i]^1].flow-=f; if(a==0) break; } } return flow; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i); //第一问,DP求LIS int max=0; f[1]=1; for(int i=2;i<=n;i++){ for(int j=1;j<i;j++) if(a[i]>a[j]&&f[j]>f[i]) f[i]=f[j]; f[i]++; if(f[i]>max) max=f[i]; } printf("%d\n",max); //第二问 buildgraph(n,max); int maxflow=0; while(BFS()){ memset(cur,0,sizeof(cur)); maxflow+=DFS(s,INF); } printf("%d\n",maxflow); //第三问 addedge(1,1+n,INF); addedge(n,n+n,INF); addedge(s,1,INF); if(f ==max) addedge(n+n,t,INF); while(BFS()){ memset(cur,0,sizeof(cur)); maxflow+=DFS(s,INF); } printf("%d\n",maxflow); return 0; }
相关文章推荐
- 线性规划与网络流24题 10餐巾计划问题
- kyeremal-网络流24题T6-最长递增子序列问题
- 网络流24题:最长递增子序列问题
- 线性规划与网络流24题之 试题库问题
- 网络流与线性规划24题05圆桌问题
- 【线性规划与网络流24题 6】最长递增子序列
- 网络流与线性规划24题02太空飞行计划问题
- 线性规划与网络流24题之最长k可重区间集问题 最大权不相交路径(最大费用最大流)
- 线性规划与网络流24题之 魔术球问题
- 餐巾计划问题 线性规划与网络流24题之10 费用流
- 网络流与线性规划24题01飞行员配对方案问题
- 网络流与线性规划24题07试题库问题
- 线性规划与网络流24题之海底机器人问题 最大费用最大流
- 线性规划与网络流24题の2 太空飞行计划问题(最大权闭合图问题)
- 线性规划以网络流24题の10 餐巾计划问题(费用流)
- 线性规划与网络流24题の4 魔术球问题(最小路径覆盖)
- 网络流与线性规划24题08机器人路径规划问题之初探索(未完成版)
- 网络流24题之T6 最长递增子序列问题
- 网络流与线性规划24题01飞行员配对方案问题
- 网络流与线性规划24题04魔术球问题