题目链接,描述
https://www.lintcode.com/problem/1538
描述
你跟你的朋友在玩一个卡牌游戏,总共有 n 张牌。每张牌的成本为 cost[i] 并且可以对对手造成 damage[i] 的伤害。你总共有 totalMoney 元并且需要造成至少 totalDamage 的伤害才能获胜。每张牌只能使用一次,判断你是否可以取得胜利。
样例
样例1
输入:
cost = [1,2,3,4,5]
damage = [1,2,3,4,5]
totalMoney = 10
totalDamage = 10
输出: true
样例说明: 我们可以使用 [1,4,5] 去造成10点伤害,总花费为10。
Example2
输入:
cost = [1,2]
damage = [3,4]
totalMoney = 10
totalDamage = 10
输出: false
样例说明:我们最多只能造成7点伤害。
思考
和lintcode 第 92题和第125题类型
答案【递归版本+缓存,动态规划版本都有】
public class Solution {
/**
* @param cost: costs of all cards
* @param damage: damage of all cards
* @param totalMoney: total of money
* @param totalDamage: the damage you need to inflict
* @return: Determine if you can win the game
*/
public boolean cardGame(int[] cost, int[] damage, int totalMoney, int totalDamage) {
/*
//递归+记忆化搜索的代码
Integer[][] dp = new Integer[cost.length+1][totalMoney+1];
int maxDamage = dfs(0,totalMoney,cost,damage,dp);
//System.out.println(maxDamage+" 是能造成的最大伤害");
return maxDamage>= totalDamage;
*/
//动态规划代码
int n = cost.length;
int[][] dp = new int[n+1][totalMoney+1];
for (int i = n-1; i >=0 ; i--) {
for (int rest = 0; rest <=totalMoney ; rest++) {
int p1 = dp[i+1][rest];
int p2 =0;
int next = (rest-cost[i]<0)?-1:(dp[i+1][rest-cost[i]]);
if(next!=-1){
p2 = next+damage[i];
}
dp[i][rest] = Math.max(p1,p2);
}
}
return dp[0][totalMoney] >= totalDamage;
}
//递归+记忆化搜索
public static int dfs(int index,int rest,int[] cost,int[] damage, Integer[][] dp ){
if(rest<0) return -1;
if(index == cost.length) return 0;
if(dp[index][rest] !=null) return dp[index][rest];
int p1 = dfs(index+1,rest,cost,damage,dp);
int p2 =0;
int next = dfs(index+1,rest-cost[index],cost,damage,dp);
if(next!=-1){
p2 = next+damage[index];
}
dp[index][rest] =Math.max(p1,p2);
return Math.max(p1,p2);
}
}