01背包问题

来源:互联网 发布:类似菠萝饭的软件 编辑:程序博客网 时间:2024/06/05 17:14

hdu 2546 饭卡

饭卡

Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 27976    Accepted Submission(s): 9706


Problem Description
电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。
 

Input
多组数据。对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
第二行包括n个正整数,表示每种菜的价格。价格不超过50。
第三行包括一个正整数m,表示卡上的余额。m<=1000。

n=0表示数据结束。
 

Output
对于每组输入,输出一行,包含一个整数,表示卡上可能的最小余额。
 

Sample Input
1505101 2 3 2 1 1 2 3 2 1500
 

Sample Output
-4532
 

Source
UESTC 6th Programming Contest Online

思路:对于饭卡上的余额,有明确的的规定,当大于等于5元时,才可以买别的东西,那么我们可以先预留5元,从给出的物品中买一件最贵的物品,另外的余额用来购买其他的物品,这时就转化成了在给定余额的情况下,能够最大获得多少价值?每种物品只有一种,就是01背包问题。

代码:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;int dp[1001][1001];int value[1001];int max(int a, int b) {    return a > b ? a : b;}void judge(int sum, int Max, int n) {    int i, j;    for(i = 1; i <= n-1; i++)        for(j = 0; j <= sum-5; j++) {            dp[i][j] = dp[i-1][j];            if(j >= value[i])                dp[i][j] = max(dp[i-1][j], dp[i-1][j-value[i]] + value[i]);        }    printf("%d\n", sum - dp[n-1][sum-5] - Max); }int compare(int a, int b) {    return a < b;}int main() {    int n, i, j, sum;    memset(dp, 0, sizeof(int)*1001*1001);    while(scanf("%d", &n), n != 0) {        for(i = 1; i <= n; i++)            scanf("%d", &value[i]);        scanf("%d", &sum);        if(sum < 5) {            printf("%d\n",sum);            continue;        }        sort(value+1, value + n +1, compare);        judge(sum, value[n], n);    }}

一维数组实现:

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;int dp[1003];int value[1003];int max(int a, int b) {    return a > b ? a : b;}void judge(int sum, int Max, int n) {    int i, j;    for(i = 1; i <= n-1; i++)        for(j = sum-5; j >= value[i]; j--) {                dp[j] = max(dp[j], dp[j-value[i]] + value[i]);        }    printf("%d\n", sum - dp[sum-5] - Max); }int compare(int a, int b) {    return a < b;}int main() {    int n, i, j, sum;    while(scanf("%d", &n), n != 0) {        memset(dp, 0, sizeof(int)*1003);        memset(value, 0, sizeof(int)*1003);        for(i = 1; i <= n; i++)            scanf("%d", &value[i]);        scanf("%d", &sum);        if(sum < 5) {            printf("%d\n",sum);            continue;        }        sort(value + 1, value + n + 1, compare);        judge(sum, value[n], n);    }}

hdu 1171  big event in hdu

Big Event in HDU

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 40252    Accepted Submission(s): 13861


Problem Description
Nowadays, we all know that Computer College is the biggest department in HDU. But, maybe you don't know that Computer College had ever been split into Computer College and Software College in 2002.
The splitting is absolutely a big event in HDU! At the same time, it is a trouble thing too. All facilities must go halves. First, all facilities are assessed, and two facilities are thought to be same if they have the same value. It is assumed that there is N (0<N<1000) kinds of facilities (different value, different kinds).
 

Input
Input contains multiple test cases. Each test case starts with a number N (0 < N <= 50 -- the total number of different facilities). The next N lines contain an integer V (0<V<=50 --value of facility) and an integer M (0<M<=100 --corresponding number of the facilities) each. You can assume that all V are different.
A test case starting with a negative integer terminates input and this test case is not to be processed.
 

Output
For each case, print one line containing two integers A and B which denote the value of Computer College and Software College will get respectively. A and B should be as equal as possible. At the same time, you should guarantee that A is not less than B.
 

Sample Input
210 120 1310 1 20 230 1-1
 

Sample Output
20 1040 40
 

Author
lcy

思路:要求把给定的所有的物品,一分为二,要求A份要大于等于B份,可以先把总的物品的价值所出来,除以2以此作为背包容量,计算最大值,一定会使得A份大于等于B份。与01背包不同的是,它的数量不一定都是1,这个题更像多重背包,可以把它转换为01背包,把n件相同的物品,看做n件(具有相同价值)不同的物品,这时只不过weight和value数组的长度变长了,其他没有什么区别。

代码:

#include<stdio.h>#include<string.h>int value[5020];int dp[250020];int max(int a, int b) {    return a > b ? a : b;}void judge(int sum, int sumValue) {    int average = sumValue / 2;    int i, j;    for(i = 1; i <= sum; i++)        for(j = average; j >= value[i]; j--) {            dp[j] = max(dp[j-value[i]] + value[i], dp[j]);        }    printf("%d %d\n", sumValue - dp[average], dp[average]);}int main() {    int n, i, j, count, sum, sumValue, a, b;    while(scanf("%d", &n), n > 0) {        memset(value, 0, sizeof(value));        memset(dp, 0, sizeof(dp));        sum = 1;        sumValue = 0;        for(i = 1; i <= n; i++) {            scanf("%d", &a);            scanf("%d", &b);            while(b--) {                value[sum++] = a;                sumValue += a;            }        }        judge(sum, sumValue);    } }

HDU2602:Bone Collector

http://acm.hdu.edu.cn/showproblem.php?pid=2602


经典的01背包问题,

代码:

#include<stdio.h>#include<string.h>int dp[1005];int value[1005];int weight[1005];int v, n;int max(int a, int b) {    return a > b ? a : b;}void judge() {    int i, j;    for(i = 1; i <= n; i++)        for(j = v; j >= weight[i]; j--)            dp[j] = max(dp[j], dp[j-weight[i]] + value[i]);    printf("%d\n", dp[v]);}int main() {    int t, i;    scanf("%d", &t);    while(t--) {        scanf("%d%d", &n, &v);        memset(dp, 0, sizeof(dp));        memset(value, 0, sizeof(value));        memset(weight, 0, sizeof(weight));        for(i = 1; i <= n; i++)            scanf("%d", &value[i]);        for(i = 1; i <= n; i++)            scanf("%d", &weight[i]);        judge();    }}

HDU 2639  Bone Collector II

http://acm.hdu.edu.cn/showproblem.php?pid=2639

这里要求第k优解,

代码:

#include<stdio.h>#include<string.h>int value[1005];int weight[1005];int dp[1005][32];int n, v, k;void judge() {    int x, y, z;    int i, j, t;    int a[32] = {0}, b[32]= {0};    for(i = 1; i <= n; i++) {        for(j = v; j >= weight[i]; j--) {            for(t = 1; t <= k; t++) {                a[t] = dp[j-weight[i]][t] + value[i];                b[t] = dp[j][t];            }            x = y = z = 1;            a[t] = b[t] = -1;            while(z <= k && (x <= k || y <= k)) {                if(a[x] > b[y]) {                    dp[j][z] = a[x];                    x++;                }                else {                    dp[j][z] = b[y];                    y++;                }                if(dp[j][z] != dp[j][z-1])                    z++;            }        }    }    printf("%d\n", dp[v][k]);}int main() {    int t, i;    scanf("%d", &t);    while(t--) {        memset(value, 0, sizeof(value));        memset(weight, 0, sizeof(weight));        memset(dp, 0, sizeof(int)*1005*32);        scanf("%d%d%d", &n, &v, &k);        for(i = 1; i <= n; i++)            scanf("%d", &value[i]);        for(i = 1; i <= n; i++)            scanf("%d", &weight[i]);        judge();    }    return 0;}


0 0
原创粉丝点击