4777: 方格取数 动态规划
描述
设有N*N的方格图(N<=10,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例):
某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
输入
输入的第一行为一个整数N(表示N*N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
输出
只需输出一个整数,表示2条路径上取得的最大的和。
样例输入
8
2 3 13
2 6 6
3 5 7
4 4 14
5 2 21
5 6 4
6 3 15
7 2 14
0 0 0
样例输出
一个四重循环枚举两条路分别走到的位置。由于每个点均从上或左继承而来,故内部有四个if,分别表示两个点从上上、上左、左上、左左继承来时,加上当前两个点所取得的最大值。
a[i][j]表示(i,j)格上的值,sum[i][j][h][k]表示第一条路走到(i,j),第二条路走到(h,k)时的最优解。
例如,sum[i][j][h][k] = max{sum[i][j][h][k], sum[i-1][j][h-1][k] + a[i][j] + a[h][k]},表示两点均从上面位置走来。
当(i,j) != (h,k))时 sum[i][j][h][k]:=max{sum[i-1][j][h-1][k],sum[i][j-1][h][k-1],sum[i-1][j][h][k-1],sum[i][j-1][h-1][k]}+a[i][j]+a[h][k];
当(i,j) = (h,k)时 sum[i][j][h][k]:=max{sum[i-1][j][h-1][k],sum[i][j-1][h][k-1],sum[i-1][j][h][k-1],sum[i][j-1][h-1][k]}+a[i][j];
1 #include<bits/stdc++.h> 2 using namespace std; 3 int f[11][11][11][11],a[11][11]; 4 int n,x,y,z; 5 int main() 6 { 7 cin>>n; 8 while(cin>>x>>y>>z) 9 { 10 if(!x&&!y&&!z)break; 11 a[x][y] = z; 12 } 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=n;j++) 15 for(int h=1;h<=n;h++) 16 for(int l=1;l<=n;l++) 17 { 18 int t1 = max(f[i-1][j][h-1][l],f[i][j-1][h][l-1]); 19 int t2 = max(f[i-1][j][h][l-1],f[i][j-1][h-1][l]); 20 f[i][j][h][l] = max(t1,t2)+a[i][j]; //计算两条路线分别到达(i,j)和(h,l)时的最优值 21 if(i!=h && j!=l)f[i][j][h][l]+=a[h][l]; //如果两条路线的点不相同,那还需要把(h,j)到达的点数值加起来 22 } 23 cout<<f[n][n][n][n]; 24 return 0; 25 }