不会这道算法题,阿里把我挂了

阿里巴巴面试题: 卡牌游戏

描述
现在有一个卡牌游戏,先给出卡牌的数量n,再给你两个非负整数totalProfit、totalCost,然后给出每张卡牌的利润值 a[i]和成本值b[i],现在可以从这些卡牌中任意选择若干张牌,组成一个方案,问有多少个方案满足所有选择的卡牌利润和大于totalProfit且成本和小于totalCost。

  • 由于这个数可能很大,因此只需返回方案数对1e9 + 7取模的结果。
  • 0≤n≤100
  • 0≤totalProfit≤100
  • 0≤totalCost≤100
  • 0≤a[i]≤100
  • 0≤b[i]≤100
    在线评测地址

样例1

输入:n = 2,totalProfit = 3,totalCost = 5,a = [2,3],b = [2,2] 
输出:1
解释:
此时只有一个合法的方案,就是将两个卡牌都选上,此时a[1]+a[2] = 5 > totalProfit 且 b[1] + b[2] < totalCost,满足题意。

样例 2:

输入:n = 3,totalProfit = 5,totalCost = 10,a = [6,7,8],b = [2,3,5]
输出: 6
解释:
假设一个合法方案(i,j)表示选择了第i张卡牌和第j张卡牌。
则此时合法的方案有:
(1),(2),(3),(1,2),(1,3),(2,3)

解题思路
假设dp[i][j]dp[i][j]为卡牌利润和等于ii且成本和等于jj的方案数。 则按顺序枚举每一个卡牌xx,同时更新dpdp数组,有: dp[i+a[x]][j+b[x]]+=dp[i][j]dp[i+a[x]][j+b[x]]+=dp[i][j]
dp递推关系式的推导可以类比背包问题,代码中的totalProfit+1即表示利润大于totalProfit的方案数,totalCost同理,因为有: int now_p = min(totalProfit + 1, p + ai); int now_c = min(totalCost + 1, c + bi); 限制Profit最大为totalProfit + 1,Cost最大为totalCost + 1。
时间复杂度:O(n∗totalProfit∗totalCost+totalCost)

源代码

public class Solution
{
    /**
     * @param n: The number of cards
     * @param totalProfit: The totalProfit
     * @param totalCost: The totalCost
     * @param a: The profit of cards
     * @param b: The cost of cards
     * @return: Return the number of legal plan
     */
    public int numOfPlan(int n, int totalProfit, int totalCost, int[] a, int[] b) {
        // Write your code here
        long mod = 1000000007;
        long [][][]dp;
        dp = new long [150][150][150];
        int i, j, k;
        for (i = 0; i <= 105; i++)
            for (j = 0; j <= 105; j++)
                for (k = 0; k <= 105; k++) {
                    dp[i][j][k] = 0;
                }
        dp[0][0][0] = 1;
        for (k = 0; k < n; k++)
            for (i = 0; i <= totalProfit + 1; i++)
                for (j = 0; j < totalCost; j++)  
                  if (dp[k][i][j] > 0) {
                        dp[k + 1][i][j] += dp[k][i][j];
                        dp[k + 1][i][j] %= mod;
                        if (j + b[k] < totalCost) {
                            dp[k + 1][Math.min(totalProfit + 1, i + a[k])][j + b[k]] += dp[k][i][j];
                            dp[k + 1][Math.min(totalProfit + 1, i + a[k])][j + b[k]] %= mod;
                        }
                    }
        long sum;
        sum = 0;
        for (j = 0; j < totalCost; j++) {
            sum = (sum + dp[n][totalProfit + 1][j]) % mod;
        }
        return (int)sum;
    }
}

更多题解参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值