P1006 传纸条
三维dp。
想一下,就是传两张纸条,其实简化一下就是两个点,一个点的路线恒在另一个的左边。
只是这样吗?很明显不是的。这是同步的,所以两个点始终在他的斜线上。例如
0 1 2
1 2 0
2 0 0
接下来,下面的1,和上面的1都走一步时,一定会在2斜线上。
这样,枚举斜线(每一个点的和相等),记录每一个点的纵坐标,即可记录好状态。
f [ k ] [ i ] [ j ]=max( 上一条斜线的两个点的上下左右 )+map[ k-i ][ i ]+map[ k-j ][ j ];
很有趣的一道题。。。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 #define mid ((l+r)>>1) 8 #define maxn 150 9 #define mod 10000 10 #define reg register 11 #define ll long long 12 #define ull unsigned long long 13 #define inf 0x3f3f3f3f 14 #define rep(a,b,c) for(reg int a=b;a<=c;a++) 15 #define Rep(a,b,c) for(reg int a=b;a<c;a++) 16 #define down(a,b,c) for (reg int a=b;a>=c;a--) 17 #define Down(a,b,c) for (reg int a=b;a>c;a--) 18 19 //struct yl{ 20 // int beg,sto,til; 21 //}s[maxn]; 22 int f[200][100][100],n,m; 23 int map[1010][1010]; 24 25 inline int read() 26 { 27 char ch=getchar(); 28 int k=0,sign=1; 29 while (ch<'0' || ch>'9') { 30 if (ch=='-') sign=-1; 31 ch=getchar(); 32 } 33 while (ch>='0'&&ch<='9') k=k*10+(ch^48),ch=getchar(); 34 return k*sign; 35 } 36 //bool cmp(yl a,yl b) {return a.beg>b.beg;} 37 //int gcd(int x,int y){return x%y==0?y:gcd(y,x%y);} 38 39 //void P() 40 //{ 41 // rep(i,mod,mod+mod) 42 // { 43 // printf("%d",f[n][i]); 44 // putchar(10); 45 // } 46 //} 47 int main() 48 { 49 // freopen("qnm.in","r",stdin); 50 // freopen("cnm.out","w",stdout); 51 m=read();n=read(); 52 rep(i,1,m) rep(j,1,n) map[i][j]=read(); 53 Rep (k,3,m+n) Rep(i,1,n) rep(j,i+1,n) 54 { 55 f[k][i][j]=max(max(f[k-1][i][j],f[k-1][i-1][j]),max(f[k-1][i][j-1],f[k-1][i-1][j-1])); 56 if (f[k][i][j]==-1) 57 { 58 f[k][i][j]=0;continue; 59 } 60 else 61 { 62 f[k][i][j]+=(map[k-i][i]+map[k-j][j]); 63 } 64 } 65 printf("%d\n",f[m+n-1][n-1][n]); 66 return 0; 67 }