1277:【例9.21】方格取数
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 1317 通过数: 953
【题目描述】
设有N×N的方格图,我们在其中的某些方格中填入正整数,而其它的方格中则放入数字0。如下图所示:
某人从图中的左上角A出发,可以向下行走,也可以向右行走,直到到达右下角的B点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B点共走了两次,试找出两条这样的路径,使得取得的数字和为最大。
【输入】
第一行为一个整数N(N≤10),表示N×N的方格图。
接下来的每行有三个整数,第一个为行号数,第二个为列号数,第三个为在该行、该列上所放的数。一行“0 0 0”表示结束。
【输出】
第一个整数,表示两条路径上取得的最大的和。
【输入样例】
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
【输出样例】
67
思路:
相当于两个人同时走,求最大值,
dp[i][j][x][y]:=第1个人走到坐标(i,j) 第2个人走到坐标(x,y) 时,最大的值
但无论如何,同一时间,1和2走的步数是一样多的,设为p,且i+j-2=p;x+y-2=p
那么dp[i][j][x][y]可以降维为:dp[i][x][p]
那么对于dp[i][x][p],就有4种情况:dp[i][x][p-1],dp[i-1][x-1][p-1],dp[i-1][x][p-1],dp[i][x-1][p-1]
求出最大值再加上a[i][j],a[x][y]
当i==x的时候,显然多加了一次
最后,注意一定要初始化:dp[1][1][0]=a[1][1],不然会出错
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<cmath>
#include<set>
#include<map>
#include<functional>
using namespace std;
#define ll long long
typedef pair<ll,int>P;
const ll INF=1e17+10;
const int N=15,mod=1e9+7;
int a[N][N];
int dp[N][N][2*N];
int main(){
int n;
scanf("%d",&n);
int x,y,k;
while(scanf("%d%d%d",&x,&y,&k)&&x+y+k!=0){
a[x][y]=k;
}
dp[1][1][0]=a[1][1];
for(int p=1;p<=2*n-2;p++){//步数
for(int i=1;i<=n;i++){
for(int x=1;x<=n;x++){
int j=p+2-i,y=p+2-x;
int tmp=max(dp[i][x][p-1],dp[i-1][x-1][p-1]);
tmp=max(tmp,dp[i-1][x][p-1]);
tmp=max(tmp,dp[i][x-1][p-1]);
dp[i][x][p]=tmp+a[i][j]+a[x][y];
if(i==x)dp[i][x][p]-=a[x][y];
}
}
}
printf("%d\n",dp[n][n][2*n-2]);
}