首页 > 试题广场 >

龙与地下城游戏问题

[编程题]龙与地下城游戏问题
  • 热度指数:390 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个二维数组map,含义是一张地图,例如,如下矩阵

游戏的规则如下:
1)骑士从左上角出发,每次只能向右或向下走,最后到达右下角见到公主。
2)地图中每个位置的值代表骑士要遭遇的事情。如果是负数,说明此处有怪兽,要让骑士损失血量。如果是非负数,代表此处有血瓶,能让骑士回血。
3)骑士从左上角到右下角的过程中,走到任何一个位置时,血量都不能少于1。为了保证骑土能见到公主,初始血量至少是多少?
根据map,输出初始血量。

数据范围:矩阵的长宽都满足 ,矩阵中的值满足
示例1

输入

[[-2,-3,3],[-5,-10,1],[0,30,-5]]

输出

7
示例2

输入

[[1,1],[1,1]]

输出

1
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param mp int整型二维数组 
 * @param mpRowLen int mp数组行数
 * @param mpColLen int* mp数组列数
 * @return int整型
 */
int max(int a,int b)
{
    if(a>b)
    return a;
    return b;
}
int min(int a,int b)
{
    if(a<b)
    return a;
    return b;
}
int dnd(int** mpint mpRowLenintmpColLen ) {
    if(mpRowLen==0||*mpColLen==0)
        return 1;
    int dp[*mpColLen+2][mpRowLen+2];
    for(int i=0;i<mpRowLen;i++)
    {
        for(int j=0;j<*mpColLen;j++)
        dp[i][j]=1000000;
    }
    dp[mpRowLen][*mpColLen]= 1-mp[mpRowLen-1][*mpColLen-1];
    for(int i=mpRowLen-1;i>0;i--)
        {
            dp[i][*mpColLen]=dp[i+1][*mpColLen]-mp[i-1][*mpColLen-1];
        }
    for(int j=*mpColLen-1;j>0;j--)
        dp[mpRowLen][j]=dp[mpRowLen][j+1]-mp[mpRowLen-1][j-1];
    for(int i=mpRowLen-1;i>0;i--)
    {
        for(int j=*mpColLen-1;j>0;j--)
        dp[i][j]=max(min(dp[i][j+1],dp[i+1][j])-mp[i-1][j-1],1-mp[i-1][j-1]);
    }
    if(dp[1][1]<=0)
        dp[1][1]=1;
    return dp[1][1];
}
发表于 2022-09-27 16:38:29 回复(0)
我头一次见到保证能见到公主的骑士血量在走到第二个格子就嗝屁的
发表于 2022-09-11 22:02:56 回复(2)
import java.util.*;
public class Solution {
    //经典的动态规划问题,定义和地图大小一样的矩阵,记为dp,dp[i][j]的含义是如果骑士要走上位置(i,j)
    //并且从该位置选一条最优的路径,最后走到右下角,骑士起码应该具备的血量。最终我们需要的是dp[0][0]
    //如果骑士在当前位置加完血或者扣完血之后的血量只要等于dp[i][j+1]即可
    //那么骑士在加血或者扣血之前的血量要求,就是dp[i][j+1]-mp[i][j]。
    //同时要求骑士血量随时不少于1,所以向右的要求为max{dp[i][j+1]-map[i][j],1},向下走也是同样的分析
    //因为骑士要走最优的一条,所以,dp[i][j]=min{向右的要求,向下的要求}
    public int dnd (ArrayList<ArrayList<Integer>> mp) {
       if(mp==null||mp.size()==0||mp.get(0)==null||mp.get(0).size()==0) return 1;
        int row=mp.size();
        int col=mp.get(0).size();
        int[][] dp=new int[row--][col--];
        dp[row][col]=mp.get(row).get(col)>0?1:-mp.get(row).get(col)+1;
        for(int j=col-1;j>=0;j--){
            dp[row][j]=Math.max(dp[row][j+1]-mp.get(row).get(j),1); 
        }
        int right=0;
        int down=0;
        for(int i=row-1;i>=0;i--){
            dp[i][col]=Math.max(dp[i+1][col]-mp.get(i).get(col),1);
            for(int j=col-1;j>=0;j--){
                right=Math.max(dp[i][j+1]-mp.get(i).get(j),1); //向右的要求
                down=Math.max(dp[i+1][j]-mp.get(i).get(j),1); //向下的要求
                dp[i][j]=Math.min(right,down);  //dp[i][j]=min{right,down}
            }
        }
        return dp[0][0];
    }
}

发表于 2022-08-09 16:45:12 回复(0)
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param mp int整型vector<vector<>> 
     * @return int整型
     */
    int dnd(vector<vector<int> >& mp) {
        // write code here
        int m = mp.size() , n = mp[0].size();
        vector<vector<int>> dp(m,vector<int>(n,1));
        dp[m-1][n-1] = 1;
        for(int j = n - 2; j >= 0;j--){
            dp[m-1][j] = max(dp[m - 1][j + 1] - mp[m - 1][j + 1],1);
        }
        for(int i = m - 2;i >= 0;i--){
            dp[i][n-1] = max(dp[i + 1][n-1] - mp[i + 1][n - 1],1);
        }
        for(int i = m - 2;i >= 0;i--){
            for(int j = n - 2;j >= 0;j--){
                dp[i][j] = min(max(dp[i + 1][j] - mp[i + 1][j],1),max(dp[i][j + 1] - mp[i][j + 1],1));
            }
        }
        return max(dp[0][0] - mp[0][0],1);
    }
};

发表于 2022-07-03 17:14:50 回复(0)