【Lintcode】1448. Card Game

2022-07-27,,

题目地址:

https://www.lintcode.com/problem/card-game/description

给定

n

n

n个物品,其价值为数组

A

A

A,成本为数组

B

B

B,问在给定总预算

c

c

c和最小总价值

p

p

p的情况下,有多少个组合可以使得总成本是小于

c

c

c,并且总价值是大于

p

p

p的。题目保证每个物品的价值和成本都是非负的(注意,这里可以是

0

0

0)。答案模

1

0

9

+

7

10^9+7

109+7后返回。

思路是动态规划。设

f

[

i

]

[

j

]

[

k

]

f[i][j][k]

f[i][j][k]是前

i

i

i个物品(从

0

0

0开始计数),总价值大于等于

j

j

j并且成本恰好等于

k

k

k的方案数。那么根据第

i

i

i个物品是否选,可以分为两种情况,如果不选,那么方案数就是

f

[

i

1

]

[

j

]

[

k

]

f[i-1][j][k]

f[i1][j][k];如果选,那么方案数就是

f

[

i

1

]

[

max

{

0

,

j

A

[

i

]

}

]

[

k

B

[

i

]

]

f[i-1][\max\{0,j-A[i]\}][k-B[i]]

f[i1][max{0,jA[i]}][kB[i]],所以就有:

f

[

i

]

[

j

]

[

k

]

=

f

[

i

1

]

[

j

]

[

k

]

+

f

[

i

1

]

[

max

{

0

,

j

A

[

i

]

}

]

[

k

B

[

i

]

]

f[i][j][k]=f[i-1][j][k]+f[i-1][\max\{0,j-A[i]\}][k-B[i]]

f[i][j][k]=f[i1][j][k]+f[i1][max{0,jA[i]}][kB[i]]边界条件,考虑第

0

0

0个物品是否选。如果不选,则

f

[

0

]

[

0

]

[

0

]

=

1

f[0][0][0]=1

f[0][0][0]=1,别的

f

[

0

]

[

.

>

0

]

[

0

]

=

0

f[0][.>0][0]=0

f[0][.>0][0]=0;如果选,则

f

[

0

]

[

.

A

[

0

]

]

[

B

[

i

]

]

=

1

f[0][.\le A[0]][B[i]]=1

f[0][.A[0]][B[i]]=1,所以算

f

[

0

]

f[0]

f[0]的时候,要将两种情况加总。代码如下:

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
        int MOD = (int) (1E9 + 7);
        
        // dp[i][j][k]是从前i + 1个物品里选,价值大于等于j的且成本恰好等于k的组合总数
        int[][][] dp = new int[n][totalProfit + 2][totalCost];
        
        // 如果第0个物品不选
        dp[0][0][0] = 1;
        for (int i = 0; i <= Math.min(a[0], totalProfit + 1); i++) {
        	// 这里要注意b[0] = 0的情况,所以要写成 += 1
            dp[0][i][b[0]] += 1;
        }
        
        for (int i = 1; i < n; i++) {
            for (int j = 0; j <= totalProfit + 1; j++) {
                for (int k = 0; k < totalCost; k++) {
                    dp[i][j][k] = dp[i - 1][j][k];
                    if (k >= b[i]) {
                        dp[i][j][k] += dp[i - 1][Math.max(0, j - a[i])][k - b[i]];
                    }
                    
                    dp[i][j][k] %= MOD;
                }
            }
        }
        
        int res = 0;
        for (int i = 0; i < totalCost; i++) {
            res += dp[n - 1][totalProfit + 1][i];
            res %= MOD;
        }
        
        return res;
    }
}

时空复杂度

O

(

n

p

c

)

O(npc)

O(npc)

可以用滚动数组优化。代码如下:

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
        int MOD = (int) (1E9 + 7);
        // dp[i][j][k]是从前i + 1个物品里选,价值大于等于j的且成本恰好等于k的组合总数
        int[][][] dp = new int[2][totalProfit + 2][totalCost];
        
        dp[0][0][0] = 1;
        for (int i = 0; i <= Math.min(a[0], totalProfit + 1); i++) {
            dp[0][i][b[0]] += 1;
        }
        
        for (int i = 1; i < n; i++) {
            for (int j = 0; j <= totalProfit + 1; j++) {
                for (int k = 0; k < totalCost; k++) {
                    dp[i & 1][j][k] = dp[i - 1 & 1][j][k];
                    if (k >= b[i]) {
                        dp[i & 1][j][k] += dp[i - 1 & 1][Math.max(0, j - a[i])][k - b[i]];
                    }
                    
                    dp[i & 1][j][k] %= MOD;
                }
            }
        }
        
        int res = 0;
		for (int i = 0; i < totalCost; i++) {
            res += dp[n - 1 & 1][totalProfit + 1][i];
            res %= MOD;
        }        

        return res;
    }
}

时间复杂度不变,空间

O

(

p

c

)

O(pc)

O(pc)

本文地址:https://blog.csdn.net/qq_46105170/article/details/110121972

《【Lintcode】1448. Card Game.doc》

下载本文的Word格式文档,以方便收藏与打印。