2019沈阳网络赛(C)Dawn-K's water完全背包

Dawn-K recently discovered a very magical phenomenon in the supermarket of Northeastern University: The large package is not necessarily more expensive than the small package.

On this day, Dawn-K came to the supermarket to buy mineral water, he found that there are n types of mineral water, and he already knew the price p and the weight c (kg) of each type of mineral water. Now Dawn-K wants to know the least money a he needs to buy no less than m kilograms of mineral water and the actual weight b of mineral water he will get. Please help him to calculate them.

Input

The input consists of multiple test cases, each test case starts with a number n (1≤n≤103) – the number of types, and mm (1≤m≤10^4) – the least kilograms of water he needs to buy. For each set of test cases, the sum of n does not exceed 5e4.

Then followed n lines with each line two integers p (1≤p≤109) – the price of this type, and c (1≤c≤104) – the weight of water this type contains.

Output

For each test case, you should output one line contains the minimum cost a and the weight of water Dawn-K will get b. If this minimum cost corresponds different solution, output the maximum weight he can get.

(The answer a is between 1 and 10^9, and the answer b is between 1 and 10^4

样例输入复制

3 3
2 1
3 1
1 1
3 5
2 3
1 2
3 3

样例输出复制

3 3
3 6

链接:

https://nanti.jisuanke.com/t/41401

题意:

有n种矿泉水,给出你每种矿泉水的价格和水量,现在给你一个m,让你求水量不少于m所花的最小价值,如果最小价值相同,则输出他可以获得的最大重量。每种水可以买多次。

解析:

完全背包模型。

我们可以dp[i]表示水量为i时花费的最小价值。

利用完全背包模型即可。因为求的最小值,初始值应为INF,边界dp[0] = 0;

因为答案的范围为1-10000,我们可以从m遍历到10000,找最小的价值。如果相同,取后面遍历到的。

代码:

#include 
using namespace std;
const int maxn = 1000+20;
const int INF = 0x3f3f3f3f;
int p[maxn], v[maxn];
int dp[10000+50];
int main()
{
    int n, m;
    while(scanf("%d %d", &n, &m)!=EOF) {
        for(int i = 1; i <= n; i++) {
            scanf("%d %d", &p[i], &v[i]);
        }
        memset(dp, INF, sizeof(dp));
        dp[0] = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = v[i]; j <= 10000; j++) {
                dp[j] = min(dp[j], dp[j-v[i]] + p[i]);
            }
        }

        int maxx = dp[m];
        int ans = m;
        for(int i = m; i <= 10000; i++) {
            if(dp[i] <= maxx) {
                maxx = dp[i];
                ans = i;
            }
        }
        printf("%d %d\n",maxx, ans);
     
    }


    return 0;
}

你可能感兴趣的:(DP,完全背包)