题意:N*N的网格图,有些格点上有数字,从左上角到右下角走两次,使得取得的数字总和最大(取走后格点数字为零)
分析:两次作为一次,即同时走,直接四层for循环,每次两个点[i,j]和[k,l]同时转移,然后再判断一下,[i,j]和[k,l]是否是同一个点,如果是同一个点,减去一个数字即可.
int a[10][10],f[10][10][10][10];
int main(){
int n=read();
while(1){
int x=read(),y=read(),z=read();
if(!x&&!y&&!z)break;
a[x][y]=z;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=n;k++)
for(int l=1;l<=n;l++){
f[i][j][k][l]=max(f[i-1][j][k-1][l],max(f[i][j-1][k-1][l],max(f[i-1][j][k][l-1],f[i][j-1][k][l-1])))+a[i][j]+a[k][l];
if(i==k&&j==l)f[i][j][k][l]-=a[i][j];
}
printf("%d\n",f[n][n][n][n]);
return 0;
}
题意:m*n的矩阵,左上角和右下角的权值为零,从左上角走到右下角,再从右下角走到左上角,要求不能经过同一个点,求经过路径权值和最大值.
分析:首先就看作两次从左上角到右下角这个转化是没有问题的吧.然后接着考虑上题是走过一次之后权值为零,但还可以走;本题是走过一次之后不能再走了.但对于动态规划来说,这是没有区别的,为什么呢?因为上题中走过一次之后权值为零的点,第二次绝对不会再走了,因为动态规划处理的是最优性问题.
跟上面的代码一样
int a[51][51],f[51][51][51][51];
int main(){
int m=read(),n=read();
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
a[i][j]=read();
}
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)
for(int l=1;l<=n;l++){
f[i][j][k][l]=max(f[i-1][j][k-1][l],max(f[i-1][j][k][l-1],max(f[i][j-1][k-1][l],f[i][j-1][k][l-1])))+a[i][j]+a[k][l];
if(i==k&&j==l)f[i][j][k][l]-=a[i][j];
}
printf("%d\n",f[m][n][m][n]);
return 0;
}