NYOJ61 传纸条(一)
本题是一道双DP问题,我第一次看到这题不知怎么办,在网上参考了别人的代码!大概理解了这类题的做法!主要是简化时间即减小维数!
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 int v[52][52],f[102][52][52]; 6 int main(){ 7 int i,j,k,t,c,T,m,n; 8 scanf("%d",&T); 9 while(T--){ 10 scanf("%d%d",&m,&n); 11 memset(v,0,sizeof(v)); 12 memset(f,0,sizeof(f)); 13 for(i=1;i<=m;i++) 14 for(j=1;j<=n;j++) 15 scanf("%d",&v[i][j]); 16 c=m+n-2; 17 for(k=1;k<c;k++){ 18 t=k+2>m?m:k+2; //t最大取m 19 for(i=1;i<=t;i++)//横坐标不超过步数和m 20 for(j=i+1;j<=t;j++)//因为i和j总会有一个永远在另一个的前面(即横坐标大于另一个的横坐标, 21 //这里设定i永远大于j),所以这里应从i+1开始,简化了一些时间。 22 f[k][i][j]=max(max(f[k-1][i][j],f[k-1][i][j-1]),max(f[k-1][i-1][j],f[k-1][i-1][j-1])) 23 +v[i][k-i+2]+v[j][k-j+2];//递推式 24 } 25 f[c][m][m]=max(f[c-1][m-1][m],f[c-1][m][m-1]);//最后一步,选取最大的一个,肯定是一个从左侧过来,另一个从上侧过来 26 printf("%d\n",f[c][m][m]); 27 } 28 return 0; 29 }