最長不下降子串行問題

2022-04-09 11:31:21 字數 1834 閱讀 7451

題目建模很好

建模思路**:byvoid(dalao十年前的題解orz)

「問題分析」

第一問是lis,動態規劃求解,第二問和第三問用網路最大流解決。

「建模方法」

首先動態規劃求出f[i],表示以第i位為開頭的最長上公升序列的長度,求出最長上公升序列長度k。

1、把序列每位i拆成兩個點和,從到連線一條容量為1的有向邊。

2、建立附加源s和匯t,如果序列第i位有f[i]=k,從s到連線一條容量為1的有向邊。

3、如果f[i]=1,從到t連線一條容量為1的有向邊。

4、如果j>i且a[i] < a[j]且f[j]+1=f[i],從到連線一條容量為1的有向邊。

求網路最大流,就是第二問的結果。把邊(<1.a>,<1.b>)(,)(s,<1.a>)(,t)這四條邊的容量修改為無窮大,再求一次網路最大流,就是第三問結果。

「建模分析」

上述建模方法是應用了一種分層圖的思想,把圖每個頂點i按照f[i]的不同分為了若干層,這樣圖中從s出發到t的任何一條路徑都是乙個滿足條件的最長上公升子串行。由於序列中每個點要不可重複地取出,需要把每個點拆分成兩個點。單位網路的最大流就是增廣路的條數,所以最大流量就是第二問結果。第三問特殊地要求x1和xn可以重複使用,只需取消這兩個點相關邊的流量限制,求網路最大流即可。

#include #include #include #include using std::memset;

using std::max;

using std::queue;

using std::memcpy;

const int inf=0x3f3f3f3f;

const int n=3005,s=0,t=1001;

int n,a[n],f[n],ecnt=1,head[n],cur[n];

struct edge e[n<<2];

void add(int bg,int ed,int val)

void insert(int a,int b,int v)

int h[n];

queueq;

bool bfs()

} }return h[t]!=-1;

}int dfs(int x,int f)

} if(!used)h[x]=-1;

return used;

}int maxflow;

void dinic()

}int main()

} f[n+1]=max(f[n+1],1);

printf("%d\n",f[n+1]);

if(f[n+1]==1)

for(int i=1; i<=n; i++)

for(int i=1;i<=n;i++)

for(int j=i+1;j<=n;j++)

dinic();

printf("%d\n",maxflow);

memset(head,0,sizeof head);ecnt=1;

for(int i=1,v;i<=n;i++)

for(int i=1;i<=n;i++)

for(int j=i+1;j<=n;j++)

if(a[j]>=a[i]&&f[j]==f[i]+1) insert(i+500,j,1);

dinic();

printf("%d",maxflow);

}

最長不下降子串行問題

前幾天看了關於動態規劃的內容,基本上講的都是最大不下降序列,所以第一次部落格 就寫這個東西了。給出一系列的數,給出乙個整數,即最長不下降子串行 code vs 1567 題解 先另創乙個陣列,用來記錄某乙個數到目前為止的最大長度,用for語句將所有元素遍歷 一遍就可以確定最長不下降子串行的長度了。比...

最長不下降子串行問題

第一問 lis 求出 s 用正常的 o n 2 的演算法,後面有用 第二問首先動態規劃求出 f i 然後根據題意 最多可取出多少個長度為s的不下降子串行 說明子串行的起點一定在 i 當且僅當 f i s 終點在 j 當且僅當 f j 1 又因為這是網路流24題每個數只能被選一次,所以把每個數對應到點...

最長不下降子串行

a1 t0 an a an 1 2 b an c d n 1 求該序列最長不下降子串行長度 n不是很大顯然可以暴力。n很大呢?那就不斷減迴圈節長度直至減到乙個閾值內,再暴力。正確性顯然,只要閾值不要設太小。include include include define fo i,a,b for i a...