JerryZhou同学经常改编习题给自己做。
这天,他又改编了一题。。。。。
设有N*N的方格图,我们将其中的某些方格填入正整数,
而其他的方格中放入0。
某人从图得左上角出发,可以向下走,也可以向右走,直到到达右下角。
在走过的路上,他取走了方格中的数。(取走后方格中数字变为0)
此人从左上角到右下角共走3次,试找出3条路径,使得取得的数总和最大。
第一行:N (4<=N<=20)
接下来一个N*N的矩阵,矩阵中每个元素不超过80,不小于0
一行,表示最大的总和。
4 1 2 3 4 2 1 3 4 1 2 3 4 1 3 2 4
39
各个测试点1s
多进程DP
就像传纸条。。。恩
第一次居然ce了 忘了memset的cstring了!!!!!
F[X][Y][J][K]表示第一次取到x和y
第二次取到j x+y-j
第三次取到k x+y-k时取到的最大值
然后要判断 可能走一个格子 这时候另一次要+0
#include
#include
#include
using namespace std;
int s[22][22];
int f[22][22][22][22];
int m,a,b,c;
int move(int bu,int x1,int x2,int x3)
{
int y1=bu-x1,y2=bu-x2,y3=bu-x3;
if(x1==x2&&x2==x3)return s[x1][y1];
if(x1==x2&&x2!=x3)return s[x1][y1]+s[x3][y3];
if(x1!=x2&&x2==x3)return s[x1][y1]+s[x3][y3];
if(x1==x3&&x2!=x3)return s[x1][y1]+s[x2][y2];
if(x1!=x2&&x2!=x3&&x3!=x1)return s[x1][y1]+s[x2][y2]+s[x3][y3];
return 0;
}
int work(int x,int y,int j,int k)
{
int bu=x+y;
if(x>m||y>m||j>m||k>m||bu-j>m||bu-k>m)return 0;
if(x<=0||y<=0||j<=0||k<=0||bu-j<=0||bu-k<=0)return 0;
if(f[x][y][j][k]!=-1)return f[x][y][j][k];
f[x][y][j][k]=max(f[x][y][j][k],work(x-1,y,j,k)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x-1,y,j-1,k)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x-1,y,j,k-1)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x-1,y,j-1,k-1)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x,y-1,j,k)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x,y-1,j-1,k)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x,y-1,j,k-1)+move(x+y,x,j,k));
f[x][y][j][k]=max(f[x][y][j][k],work(x,y-1,j-1,k-1)+move(x+y,x,j,k));
return f[x][y][j][k];
}
int main()
{
scanf("%d",&m);
memset(f,-1,sizeof(f));
for(a=1;a<=m;a++)
for(b=1;b<=m;b++)
scanf("%d",&s[a][b]);
cout<
现在只会递归。。。
求不爆栈
NOIP RP++