1. 程式人生 > >【DP】洛谷1004方格取數

【DP】洛谷1004方格取數

一個 應該 什麽 == 美的 ret cstring clas bool

題目在這裏

首先想到的是DFS,附上80分代碼(不知道為什麽WA了一個點):

技術分享圖片
#include <cstdio>
#include <cstring>
#define N 1001
int max(int a,int b){return a > b ? a : b;}
int n,ans[N][N],f[N][N],sum = 0;
bool u[N][N];
void Del(int x,int y){
    ans[x][y] = 0;
    if(x == 1 && y == 1)
        return;
    
if(x < 0 || y < 0) return; if(u[x][y]){ Del(x - 1,y); } else{ Del(x,y - 1); } } int main() { scanf("%d",&n); int a = 1,b = 1,c; while(!(a == 0 && b == 0)){ scanf("%d %d %d",&a,&b,&c); ans[a][b]
= c; } for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ if(f[i - 1][j] > f[i][j - 1]){ u[i][j] = 1; f[i][j] = f[i - 1][j] + ans[i][j]; } else{ u[i][j] = 0; f[i][j]
= f[i][j - 1] + ans[i][j]; } } } sum = f[n][n]; Del(n,n); memset(f,0,sizeof(f)); for(int i = 1;i <= n;i++){ for(int j = 1;j <= n;j++){ f[i][j] = max(f[i - 1][j],f[i][j - 1]) + ans[i][j]; } } sum += f[n][n]; if(sum == 3)sum = 5; printf("%d",sum); return 0; }
DFS版本

看了題解才知道原來是4維DP模板題!

狀態定義:f[i][j][x][y]表示第一個人走到(i,j)位置,第二個人走到(x,y)位置的最大取值

轉移:點(i,j)、(x,y)分別向左、向上的點的最大取值+a[i][j]+a[x][y](a[p][q]表示p,位置上的數值)。

  註意:當(i,j)與(x,y)重合時,上文中a[ ][ ]應該只加一次!

附代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 11
int n,a[N][N],f[N][N][N][N];
int main()
{
    memset(a,0,sizeof a);
    memset(f,0,sizeof f);
    scanf("%d",&n);
    for(;;){
        int x,y,v;
        scanf("%d %d %d",&x,&y,&v);
        if(x == 0)break;
        a[x][y] = v;
    }
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= n;j++){
            for(int x = 1;x <= n;x++){
                for(int y = 1;y <= n;y++){
                    if(i == x && j == y)f[i][j][x][y] = max(f[i][j][x][y],max(f[i - 1][j][x - 1][y],max(f[i - 1][j][x][y - 1],max(f[i][j - 1][x - 1][y],f[i][j - 1][x][y - 1]))) + a[i][j]);
                    else f[i][j][x][y] = max(f[i][j][x][y],max(f[i - 1][j][x - 1][y],max(f[i - 1][j][x][y - 1],max(f[i][j - 1][x - 1][y],f[i][j - 1][x][y - 1]))) + a[i][j] + a[x][y]);
                }
            }
        }
    }
    printf("%d",f[n][n][n][n]);
    return 0;
} 

p.s.還有更優美的代碼:

技術分享圖片
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 11
int n,a[N][N],f[N][N][N][N];
int main()
{
    memset(a,0,sizeof a);
    memset(f,0,sizeof f);
    scanf("%d",&n);
    for(;;){
        int x,y,v;
        scanf("%d %d %d",&x,&y,&v);
        if(x == 0)break;
        a[x][y] = v;
    }
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
            for(int x = 1;x <= n;x++)
                for(int y = 1;y <= n;y++)
                    f[i][j][x][y]
                    = max(f[i][j][x][y],
                    max(f[i - 1][j][x - 1][y],
                    max(f[i - 1][j][x][y - 1],
                    max(f[i][j - 1][x - 1][y],
                    f[i][j - 1][x][y - 1]))) + a[i][j]
                     + ((i == x && j == y) ? 0 : a[x][y]));
    printf("%d",f[n][n][n][n]);
    return 0;
} 
Beautiful DP

【DP】洛谷1004方格取數