NYOJ 61 传纸条是一个双线DP的题:
从矩阵的左上角(1,1)点到矩阵的右下角(m,n)点找到两条不相交的路径使其值最大,
题中是从(1,1)到(m,n)走一次,再从(m,n)到(1,1)走一次,我们可以等价变形
一下,变为:同时从(1,1)走向(m,n)找两条路,且这两条路不相交,同时走!
假设有两个人在走,一个人的坐标为(x1,y1),另一个人的坐标为(x2,y2),有题中规定
只能向下或向右走,则可得状态转移方程:
f(x1,y1,x2,y3) = max { f(x1-1,y1,x2-1,y2) ,f(x1-1,y1,x2,y-1), f(x1,y1-1,x2-1,y2), f(x1,y1-1,x2,y2-1)} + map[x1][y1] + map[x2][y2]
(map中存放同学的好心度,相当于权值)
这样写的话 时间复杂度会是O(n^4),比较大容易超时,改进:
因为 两个人是同时走的所以 每次都是同时移动一格:因此有 x1+y1==x2+y2 == k
则状态方程可以改为:
f(k,x1,x2) = ma{ f(k-1,x1,x2), f(k-1,x-1,x2) ,f(k-1,x1,x2-1), f(k-1,x1-1,x2-1) } + map[x1][k-x1] + map[x2][k-x2]
本题代码:
1 2 #include<stdio.h> 3 #include<string.h> 4 5 int a[201][101][101]; 6 int map[101][101]; 7 8 int max(int n1,int n2,int n3,int n4) 9 { 10 int s,d; 11 s = n1>n2?n1:n2; 12 d = n3>n4?n3:n4; 13 s = s>d?s:d; 14 return s; 15 } 16 17 int slove(int m,int n) 18 { 19 int x1,y1,x2,y2,k; 20 for(k=2;k<=m+n;++k) 21 for(x1=1;x1<=m;++x1) 22 for(x2=1;x2<=m;++x2) 23 { 24 y1=k-x1; 25 y2=k-x2; 26 if(y1<0 || y2<0 || y1>n || y2>n)continue; 27 if(y1==y2)continue; 28 a[k][x1][x2]=max(a[k-1][x1][x2],a[k-1][x1-1][x2], 29 a[k-1][x1][x2-1],a[k-1][x1-1][x2-1]) 30 +map[x1][y1]+map[x2][y2]; 31 } 32 return a[m+n-1][m][m-1]; 33 } 34 35 int main() 36 { 37 int t,m,n,i,j; 38 scanf("%d",&t); 39 while(t--) 40 { 41 memset(a,0,sizeof(a)); 42 scanf("%d%d",&m,&n); 43 for(i=1;i<=m;++i) 44 for(j=1;j<=n;++j) 45 scanf("%d",&map[i][j]); 46 printf("%d\n",slove(m,n)); 47 } 48 return 0; 49 } 50 51