Dilworth定理:最小链覆盖数=最大点独立集
这题要求最小链覆盖,我们可以直接转化为最大独立点集来求
考虑DP
设$f[i][j]$表示当前在位置i,j时的答案,显然$f[i][j]$可以从$f[i-1][j]$和$f[i][j+1]$转移过来(反链),但是如果要是最大独立点集的话要求独立,所以还可以从$f[i-1][j+1]$这个无法到达的地方转移过来
所以有:
$$f[i][j]=max\{f[i-1][j],f[i][j+1],f[i-1][j+1]+a[i][j]\}$$
1 //张家奇怎么又AKIOI了呀,怎么CSP也满分啊...怎么清北天天给他打电话啊...怎么会有这么强的人啊 2 #include<bits/stdc++.h> 3 #define int long long 4 #define writeln(x) write(x),puts("") 5 #define writep(x) write(x),putchar(' ') 6 using namespace std; 7 inline int read(){ 8 int ans=0,f=1;char chr=getchar(); 9 while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();} 10 while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();} 11 return ans*f; 12 }void write(int x){ 13 if(x<0) putchar('-'),x=-x; 14 if(x>9) write(x/10); 15 putchar(x%10+'0'); 16 }const int M = 1e3+5; 17 int f[M][M],a[M][M],n,m,T; 18 signed main(){ 19 for(T=read();T--;){ 20 n=read(),m=read(); 21 memset(a,0,sizeof(a)),memset(f,0,sizeof(f)); 22 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=read(); 23 for(int i=1;i<=n;i++)for(int j=m;j>=1;j--)f[i][j]=max(max(f[i-1][j],f[i][j+1]),f[i-1][j+1]+a[i][j]); 24 cout<<f[n][1]<<endl; 25 } 26 return 0; 27 }