题目描述:
设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。
某人从图的左上角的AA点出发,可以向下行走,也可以向右走,直到到达右下角的BB点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从(0, 0)点到(n,n)点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
输入格式:
输入的第一行为一个整数N(表示N×N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
如:
8
6 1 7
3 2 9
2 3 5
1 4 3
3 4 3
6 6 6
1 7 1
0 0 0
输出格式:
输出文件仅包含一个数,表示所有人都渡过河的最少渡河时间:25
思路:
动态表示:
f[k][i][j]表示走了总共k步,第一次走到了横坐标为i 的位置(纵坐标为k-i),第一次走到了横坐标为j的位置(纵坐标为k-j)。
动态转移:
四种情况(下下、下右、右下、右右)
需要注意的:两次走到过同一位置。
if(i==j){
f[k][i][j] = w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);
}
else{
f[k][i][j] = w[j][k-j]+ w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);
}
AC代码:
#include<iostream>
using namespace std;
const int N = 50;
int n;
int w[N][N];
int f[2*N][N][N];
int max(int a,int b,int c,int d){
return(max(a,max(b,max(c,d))));
}
int main(){
cin>>n;
int a,b,c;
while(cin>>a>>b>>c){
if(!a&&!b&&!c) break;
w[a][b] = c;
}
for(int k=2;k<=2*n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(i==j){
f[k][i][j] = w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);
}
else{
f[k][i][j] = w[j][k-j]+ w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);
}
}
cout<<f[2*n][n][n]<<endl;
}
加上边界考虑:
#include<iostream>
using namespace std;
int n;
int map[15][15];
int f[25][15][15];
int main() {
cin >> n;
int x, y, z;
while (cin >> x >> y >> z) {
if (!x && !y && !z) break;
map[x][y] = z;
}
for (int k = 2; k <= 2 * n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ ) {
int a = k - i, b = k - j;
if (a >= 1 && a <= n && b >= 1 && b <= n) {
int t = max(max(f[k - 1][i - 1][j], f[k - 1][i][j]), max(f[k - 1][i][j - 1], f[k - 1][i - 1][j - 1]));
if (i == j) f[k][i][j] = t + map[i][a];
else f[k][i][j] = t + map[i][a] + map[j][b];
}
}
cout << f[2 * n][n][n];
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/103332.html