【NOIP2000】方格取数
时间限制: 1 Sec 内存限制: 64 MB题目描述
设有N*N的方格图,我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。如下图所示(见样例): 某人从图的左上角的A 点出发,可以向下行走,也可以向右走,直到到达右下角的B点。
在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B 点共走两次,试找出2条这样的路径,使得取得的数之和为最大。
输入
第1行:1个整数N(N<=10),表示N*N的方格图,
第2..?行:每行有3个整数,前2个表示某个方格的位置,第3个数为该位置上所放的数。
一行单独的0表示输入结束。
输出
第1行:1个整数,表示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
样例输出
67
其实走两次可以视为两个人一起走
本来
要用
4个维度来记录2个人的位置,O(N^4)的时间复杂度,
经过优化,因为两人走的步数是可以随时相同的,用一个step来记录2人走的位置,
记录x1,x2,y=step-x+1,
优化为O(2*n^2)
注意有两者重合的情况,和两者从一个格子里取数转移状态的情况,以及边界
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
typedef long long int LL;
typedef unsigned long long int ULL;
LL getint(){
LL ans=0,f=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')f=-f;
while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
return ans*f;
}
using namespace std;
LL f[30][15][15],g[15][15];
LL max(int a,int b){return a>b?a:b;}
LL max(int a,int b,int c,int d){
return max(a,max(b,max(c,d)));
}
int main(){
int n=getint(),step,x1,x2,a,b,c,l,r;
while(1){
a=getint();b=getint();c=getint();
if(a==0)break;
g[a][b]=c;
}
//y=step-x+1;
for(step=1;step<=2*n-1;++step){
if(step<=n)l=1,r=step;
else l=step-n+1,r=n;
for(x1=l;x1<=r;++x1)
for(x2=l;x2<=r;++x2){
if(x1!=x2)f[step][x1][x2]=g[x1][step-x1+1]+g[x2][step-x2+1];
else f[step][x1][x2]=g[x1][step-x1+1];
f[step][x1][x2]+=max(f[step-1][x1][x2],f[step-1][x1-1][x2],f[step-1][x1][x2-1],f[step-1][x1-1][x2-1]);
}
}
printf("%lld\n",f[2*n-1][n][n]);
}