- Backpack IX
中文English
You have a total of n thousand yuan, hoping to apply for a university abroad. The application is required to pay a certain fee. Give the cost of each university application and the probability of getting the University’s offer, and the number of university is m. If the economy allows, you can apply for multiple universities. Find the highest probability of receiving at least one offer.
Example
Example 1:
Input:
n = 10
prices = [4,4,5]
probability = [0.1,0.2,0.3]
Output: 0.440
Explanation:
select the second and the third school.
Example 2:
Input:
n = 10
prices = [4,5,6]
probability = [0.1,0.2,0.3]
Output: 0.370
Explanation:
select the first and the third school.
Notice
0<=n<=10000,0<=m<=10000
注意,该题是01背包问题的变种,不是完全背包问题!因为每个学校只能申请一次!
class Solution {
public:
/**
* @param n: Your money
* @param prices: Cost of each university application
* @param probability: Probability of getting the University's offer
* @return: the highest probability
*/
double backpackIX(int n, vector<int> &prices, vector<double> &probability) {
vector<double> dp(n + 1, 1.0);
//dp[x] is the min probability that no one offer is received when money x are used.
int count = prices.size();
for (int i = 0; i < count; ++i) {
//for (int j = prices[i]; j <= n; ++j) { //错误!
for (int j = n; j >= prices[i]; --j) {
dp[j] = min(dp[j], dp[j - prices[i]] * (1.0 - probability[i]));
//cout<<"i = "<<i<<" j="<<j<<" "<<dp[j]<<endl;
}
}
return 1 - dp[n];
}
};
以 Input
10
[4,4,5]
[0.1,0.2,0.3]
为例,则输出为:
i = 0 j=10 0.9
i = 0 j=9 0.9
i = 0 j=8 0.9
i = 0 j=7 0.9
i = 0 j=6 0.9
i = 0 j=5 0.9
i = 0 j=4 0.9
i = 1 j=10 0.72
i = 1 j=9 0.72
i = 1 j=8 0.72
i = 1 j=7 0.8
i = 1 j=6 0.8
i = 1 j=5 0.8
i = 1 j=4 0.8
i = 2 j=10 0.56 //min(dp[10]=0.72, dp[5]*(1-price[2])=0.8 * 0.7)
i = 2 j=9 0.56
i = 2 j=8 0.7
i = 2 j=7 0.7
i = 2 j=6 0.7
i = 2 j=5 0.7
Output
0.44
这个0.56是怎么来的呢?我们要让最终答案(0.44)尽量大,那么dp[10]=0.56就要尽量小。
注意,这里的j循环一定要是从大到小。为什么呢?
我们将j循环换成下面的代码:
for (int j = prices[i]; j <= n; ++j) { //注意,这是错的!
以 上面的Input为例,则输出为:
i = 0 j=4 0.9
i = 0 j=5 0.9
i = 0 j=6 0.9
i = 0 j=7 0.9
i = 0 j=8 0.81
i = 0 j=9 0.81
i = 0 j=10 0.81
i = 1 j=4 0.8
i = 1 j=5 0.8
i = 1 j=6 0.8
i = 1 j=7 0.8
i = 1 j=8 0.64
i = 1 j=9 0.64
i = 1 j=10 0.64
i = 2 j=5 0.7
i = 2 j=6 0.7
i = 2 j=7 0.7
i = 2 j=8 0.64
i = 2 j=9 0.56
i = 2 j=10 0.49
Output
0.51
Expected
0.44
我们看到
i = 0 j=8 0.81
这里就错了,因为学校0申请了2次!注意01背包和多重背包的j循环是从大到小,完全背包的j循环是从小到大!。
代码同步在
https://github.com/luqian2017/Algorithm