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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章