POJ NO.1014 Dividing(多重背包,典例)

来源:互联网 发布:java 接口文档编写 编辑:程序博客网 时间:2024/05/29 14:48

问题描述:

有分别价值为1,2,3,4,5,6的6种物品,输入6个数字,表示相应价值的物品的数量,问一下能不能将物品分成两份,是两份的总价值相等,其中一个物品不能切开,只能分给其中的某一方,当输入六个0是(即没有物品了),这程序结束,总物品的总个数不超过20000

题目链接:POJ NO.1014

思路:

一道很经典的多重背包题目。

如果价值总和为奇数那么不可能平分,直接输出Can't be divided。

剩下的没什么好说的了代码交代的很清楚了。

PS:递推关系按照《挑战程序设计》来的,学习动态规划,一般人是不会一眼就看出端倪的,需要我们拿起纸和笔,把每一步(至少前3步)都写出来,这样会很有助于我们理解动态规划。

代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cmath>#include<queue>#include<stack>#include<cstring>#include<string>#include<vector>#include<set>using namespace std;#define X first#define Y second#define PI 3.1415926const int INF = 0x3f3f3f3f;const int MAX = 3e5;int dp[MAX];int main(){    int arr[7], cnt = 1;    while(1){        int sum = 0;        for(int i = 1; i <= 6; i++){            scanf("%d", &arr[i]);            sum += arr[i] * i;        }        if(!sum) break;        if(sum % 2){            printf("Collection #%d:\n", cnt);            printf("Can't be divided.\n\n");            cnt++;            continue;        }        memset(dp, -1, sizeof(dp));        dp[0] = 0;        int k = sum / 2;        for(int i = 1; i <= 6; i++){            for(int j = 0; j <= k; j++){                if(dp[j] >= 0){                    dp[j] = arr[i];                }else if(j < i || dp[j-i] <= 0){                    dp[j] = -1;                }else{                    dp[j] = dp[j-i] - 1;                }            }        }        if(dp[k] >= 0){            printf("Collection #%d:\n", cnt);            printf("Can be divided.\n\n");        }else{            printf("Collection #%d:\n", cnt);            printf("Can't be divided.\n\n");        }        cnt++;    }    return 0;}


0 0
原创粉丝点击