[NOIP2000]方格取数

Posted by Panda2134's Blog on July 23, 2017

链接:Luogu-P1004

思路

考虑换成两次都从(0,0)出发 ,向右/下行走。 显然两者到达终点时走过的步数相同。 因此可以让二者每次都走一步,分4种情况讨论。 注意由于步数相同不可能二者位于同一列上下相邻两格。 于是唯一的特殊情况就是二者处于同一个格子,这时这个格子的数只能取一次。 特判处理即可。 状态:$ f[x_1][y_1][x_2][y_2] $:位于 $(x_1,y_1)$ 和 $(x_2,y_2)$,而且拿了这两个点的数后行走所获得的最大数字和。 复杂度为 $ O(n^4) $ ,由于 $ n \leq 9 $,可以接受 。

代码

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 9;
const int dx[] = {0,1} ,dy[] = {1,0}; 
int N,A[MAXN+5][MAXN+5],Opt[MAXN+5][MAXN+5][MAXN+5][MAXN+5];
int main(){
	int tx,ty,tv;
	scanf("%d",&N);
	while(scanf("%d %d %d",&tx,&ty,&tv) && tx && ty && tv)
		A[tx][ty]=tv;
	for(int x1=N;x1>=1;x1--)
		for(int y1=N;y1>=1;y1--)
			for(int x2=N;x2>=1;x2--)
				for(int y2=N;y2>=1;y2--)
					if(x1+y1 == x2+y2) //Valid
						for(int j=0;j<2;j++)
							for(int k=0;k<2;k++)
							{
								int nx1=x1+dx[j],ny1=y1+dy[j],
									nx2=x2+dx[k],ny2=y2+dy[k];
								int t=A[x1][y1]+A[x2][y2]
								-A[x1][y1]*(x1==x2 && y1==y2)+Opt[nx1][ny1][nx2][ny2];
								Opt[x1][y1][x2][y2]=max(Opt[x1][y1][x2][y2],t);
							}
	printf("%d\n",Opt[1][1][1][1]);
}