日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[codevs 1906] 最长递增子序列问题

發布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [codevs 1906] 最长递增子序列问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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] 最长递增子序列问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。