VIJOS 1143 三方格取数

背景

JerryZhou同学经常改编习题给自己做。

这天,他又改编了一题。。。。。

描述

设有N*N的方格图,我们将其中的某些方格填入正整数,
而其他的方格中放入0。

某人从图得左上角出发,可以向下走,也可以向右走,直到到达右下角。

在走过的路上,他取走了方格中的数。(取走后方格中数字变为0)
此人从左上角到右下角共走3次,试找出3条路径,使得取得的数总和最大。

格式

输入格式

第一行:N (4<=N<=20)
接下来一个N*N的矩阵,矩阵中每个元素不超过80,不小于0

输出格式

一行,表示最大的总和。

样例1

样例输入

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<



话说不会递推的DP了。。。

现在只会递归。。。

求不爆栈

NOIP RP++

你可能感兴趣的:(VIJOS 1143 三方格取数)