10913 - Walking on a Grid

哈哈,又一道動歸。

這道題,狀態可以設成兩個:一個是從左上方得到的最大值,另一個是從右上方得到的最大值,狀態轉移也分開求。

f(l, i, j, k)表示狀態,其中f(0, i, j, k)表示當前(i, j)點從左上方得到的經過k個負數格子的最大值,狀態轉移方程爲:

f(0, i, j, k,) = max(f(0, i - 1, j, k + t), f(1, i - 1, j, k + t), f(0, i, j - 1, k + t)) + grid[i][j],若當前格子的值爲正,t=0,否則爲-1;同理可以寫出f(1, i, j, k)的狀態轉移方程。

我寫的時候怕格子裏的數據太大,用了LL,先把每個格子初始化爲負無窮大。若爲負無窮大,則值還沒求,若爲負無窮大+1,則無解。

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define LL long long
const LL INF = (LL)1 << 60;
int n, K;

LL f[2][80][80][10], grid[80][80];
int mod(int x)
{
    return (x + 2) % 2;
}

LL dp(int i, int j, int k, int l)
{
    if(i < 1 || j < 1 || k < 0) {
        //printf("*%d %d %d %d %lld\n", i, j, k, l, -INF + 1);
        return -INF + 1;
    }
    LL &ans = f[l][i][j][k];
    if(ans != -INF) return ans;
    int t = 0;
    ans = -INF + 1;
    if(grid[i][j] < 0) t = -1;
    if(i > 0)
        ans = max(dp(i - 1, j, k + t, l), dp(i - 1, j, k + t, mod(l - 1)));
    if(l == 0){
        if(j > 1) ans = max(ans, dp(i, j - 1, k + t, l));
    }else{
        if(j < n) ans = max(ans, dp(i, j + 1, k + t, l));
    }
    if(ans != -INF + 1){
        ans += grid[i][j];
    }
    //printf("%d %d %d %d %lld\n", i, j, k, l, f[l][i][j][k]);
    return ans;
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int con = 1;
    while(scanf("%d %d", &n, &K) == 2){
        if(!n && !K) break;
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                scanf("%lld", &grid[i][j]);

        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= n; j++)
                for(int k = 0; k <= K; k++)
                    f[0][i][j][k] = f[1][i][j][k] = -INF;

        if(grid[1][1] >= 0)
            f[0][1][1][0] = f[1][1][1][0] = grid[1][1];
        else if(K >= 1)
            f[0][1][1][1] = f[1][1][1][1] = grid[1][1];

        LL ans = -INF;
        for(int i = 0; i <= K; i++){
            ans = max(ans, dp(n, n, i, 0));
        }
        if(ans != -INF + 1){
            printf("Case %d: %lld\n", con++, ans);
        }else printf("Case %d: impossible\n", con++);
    }
    return 0;
}


發佈了113 篇原創文章 · 獲贊 12 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章