hdu_round1-1004 离开迷宫(dp)

本文介绍了一个关于迷宫寻宝的算法问题,主人公yyf需要从迷宫的起点(1,1)到达终点(N,M),期间可以砸墙并尽可能多地收集财宝,同时避免装备耐久降至0。通过动态规划的方法求解最优路径及最大财宝价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

记录一个菜逼的成长。。

离开迷宫

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 124 Accepted Submission(s): 30

Problem Description
yyf是一个日理万机的男人,但自从最近他勾搭上了女神之后便随叫随到,以至于荒废了很多事情。这天,yyf正在探索一个充满陷阱的古代迷宫,他的女神来电话了,由于离迷宫出口太远了,可能要花很多时间才能回去,所以yyf不打算原路返回,而是挥动他那强壮有力的右手砸开墙壁直接走向出口。已知yyf在(1,1)的位置,而出口在(N,M)的位置,yyf每次只会向下或向右走。
而同时又由于事发突然,yyf没能给女神准备礼物,于是他决定在回去的路上尽量多拿点迷宫里的财宝作为礼物。当然,古代的迷宫里少不了陷阱,虽然yyf实在太强了而导致所有的陷阱只能对他的装备造成1点的耐久损失,但由于yyf本来只是打算探索迷宫,所以并没有准备太好的装备,最初的耐久值仅为x,而如果装备破破烂烂的走到女神那边是非常有失风度的。所以yyf想要知道自己能否在保证最快离开迷宫的同时装备不被破坏(耐久=0时装备会破破烂烂哦),如果可以,他希望能带走尽量多的财宝,如果不行,他就只能在离开迷宫后回趟家带上自己最好的衣服和专门为女神准备的礼物了。
给你迷宫里分布着的财宝信息以及陷阱布置。yyf希望知道自己在保证装备不变成破破烂烂的情况下最多能拿多少的财宝,如果出现多个方案,yyf希望自己的装备能尽量少被陷阱打中。

Input
第一行:迷宫的大小N和M以及yyf的装备的耐久x
接下来2N行
前N行每行M个整数(),表示迷宫里(i,j)位置的财宝价值
后N行每行M个数字0或1,表示迷宫里(i,j)位置是否有陷阱(1为有)
(0<=N,M,x<=100)

Output
若有可行方案,输出在获得最大价值的情况下装备能留有的最大耐久度与可获得的财宝的最大价值。若无可行方案,则输出-1。

Sample Input
3 3 4
1 2 9
2 6 2
3 2 1
1 1 1
0 1 0
0 0 1

Sample Output
1 12

dp[i][j][k]:=(i,j)k
有如下转移:
dp[i][j][k]=max(dp[i1][j][k+b[i][j]]+a[i][j],dp[i][j][k])(k+b[i][j]x)
dp[i][j][k]=max(dp[i][j1][k+b[i][j]]+a[i][j],dp[i][j][k])(k+b[i][j]x)

dp数组初始化-1
只有当上一个状态不为-1才能转移到当前状态。。(话说好几次忘记加了

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
const int maxn = 100 + 10;
int a[maxn][maxn],b[maxn][maxn];
int dp[maxn][maxn][maxn];
int main()
{
  int n,m,x;
  while(~scanf("%d%d%d",&n,&m,&x)){
    for( int i = 1; i <= n; i++ ){
      for( int j = 1; j <= m; j++ ){
        scanf("%d",&a[i][j]);
      }
    }
    for( int i = 1; i <= n; i++ ){
      for( int j = 1; j <= m; j++ ){
        scanf("%d",&b[i][j]);
      }
    }
    cl(dp,-1);
    dp[1][1][x-b[1][1]] = a[1][1];
    for( int i = 1; i <= n; i++ ){
      for( int j = 1; j <= m; j++ ){
        for( int k = 1; k <= x; k++ ){
          if(i-1 > 0 && dp[i-1][j][k+b[i][j]] != -1 && k + b[i][j] <= x)
            dp[i][j][k] = max(dp[i-1][j][k+b[i][j]] + a[i][j],dp[i][j][k]);
          if(j-1 > 0 && dp[i][j-1][k+b[i][j]] != -1 && k + b[i][j] <= x)
            dp[i][j][k] = max(dp[i][j-1][k+b[i][j]] + a[i][j],dp[i][j][k]);
        }
      }
    }
    int ans = -1,pos;
    for( int i = 1; i <= x; i++ ){
      if(ans < dp[n][m][i]){
        ans = dp[n][m][i];
        pos = i;
      }
    }
    if(ans != -1)printf("%d %d\n",pos,ans);
    else puts("-1");
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值