题目链接:https://www.luogu.com.cn/problem/P1004
考虑让两个人同时走,设计状态则直接设f[i][j][k][m],表示第一个人走到(i,j),第二个人走到(k,m)时所取数的最大值。
当(i,j)==(k,m)时,即两个人走到同一个点,则这个点其实在第二遍的时候已经为0,所以这个点的贡献只是一次。
则有转移方程:
f[i][j][k][m]=max(f[i-1][j][k-1][m],max(f[i-1][j][k][m-1],max(f[i][j-1][k-1][m],f[i][j-1][k][m-1]))); if(i==k&&j==m) f[i][j][k][m]+=g[i][j]; else f[i][j][k][m]+=g[i][j]+g[k][m];
并且最后一维m不需要枚举,用i+j-k计算出来即可。(应该只能这样做)
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int N=10; 6 int n,res; 7 int a,b,c; 8 int g[N][N],s[N],f[N][N][N][N]; 9 int main(){ 10 scanf("%d",&n); 11 while(scanf("%d%d%d",&a,&b,&c)&&a!=0) g[a][b]=c; 12 for(int i=1;i<=n;i++) 13 for(int j=1;j<=n;j++) 14 for(int k=1;k<=n;k++){ 15 int m=i+j-k; 16 if(m<0) continue; 17 f[i][j][k][m]=max(f[i-1][j][k-1][m],max(f[i-1][j][k][m-1],max(f[i][j-1][k-1][m],f[i][j-1][k][m-1]))); 18 if(i==k&&j==m) f[i][j][k][m]+=g[i][j]; 19 else f[i][j][k][m]+=g[i][j]+g[k][m]; 20 } 21 printf("%d",f[n][n][n][n]); 22 return 0; 23 }