uva_10913 - Walking on a Grid( 普通DP )

想对了状态,结果超时,原来还需要另外一个数组标记是否访问过的
状态: dp[x][y][k][d] 表示到大(x,y)最多踏上k个负数方格且由前一个经过d的方向过来的
状态转移: dp[x][y][k][d] = max(dp[x][y][k'][d']) 保证 d'不与d相对,k根据当前方格的数值而定

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define DIM     2
#define DIR     3
#define MAXK    6
#define MAXN    76

int n, val[MAXN][MAXN], visit[MAXN][MAXN][MAXK][DIR];
int dir[][DIM] = {
        {0, -1}, {0, 1}, {1, 0}
};
long long dp[MAXN][MAXN][MAXK][DIR], INF;

long long dfs(int x, int y, int k, int d)
{
        int cur_k( k );
        cur_k -= ((val[x][y] < 0)? 1 : 0);
        if( cur_k < 0 ) {
                return INF;
        }
        if( visit[x][y][k][d] ) {
                return dp[x][y][k][d];
        }
        if( x == n && y == n ) {
                visit[x][y][k][d] = 1;
                return dp[x][y][k][d] = val[x][y];
        }
        int tx, ty;
        long long rst(INF);
        for(int i = 0; i < DIR; i ++) {
                if( 1 == (d+i) ) {
                        continue;
                }
                tx = x+dir[i][0]; ty = y+dir[i][1];
                if( tx < 1 || ty < 1 || tx > n || ty > n )  {
                        continue;
                }
                if( INF != dfs(tx, ty, cur_k, i) ) {
                        rst = max(rst, val[x][y]+dp[tx][ty][cur_k][i]);
                }
        }
        visit[x][y][k][d] = 1;
        return dp[x][y][k][d] = rst;
}


int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
        freopen("test.in", "r", stdin);
#endif
        long long rst;
        int cas(1), max_k, x, y;
        while( scanf("%d %d", &n, &max_k) ) {
                if( !n && !max_k ) {
                        break;
                }
                for(int i = 1; i <= n; i ++) {
                        for(int j = 1; j <= n; j ++) {
                                scanf("%d", &val[i][j]);
                        }
                }
                if( 1 == n && max_k < 0 ) {
                        printf("Case %d: impossible\n", cas ++); continue;
                }
                if( 1 == n ) {
                        printf("Case %d: %d\n", cas ++, val[1][1]); continue;
                }
                memset(visit, 0, sizeof(visit));
                memset(dp, -0x3F, sizeof(dp)); rst = INF = dp[0][0][0][0];
                if( INF != dfs(1, 1, max_k, 1) ) {
                        rst = max(rst, dfs(1, 1, max_k, 1));
                }
                if( INF != rst ) {
                        printf("Case %d: %lld\n", cas ++, rst); continue;
                }
                printf("Case %d: impossible\n", cas ++);
        }
        return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值