「CJOJ2736」「POJ1014」大理石分割
Problem
Description
Marsha和Bill收藏了一些大理石。他们想要把这些大理石平均分配给两个人。如果大理石的价值一样,这将很容易做到,因为他们可以简单的对半分。不幸的是,一些大理石比其他的更大或者更漂亮。因此Marsha和Bill给每个大理石都规定了一个价值,它是一个1~6之间的自然数。现在他们想要把这些大理石分成两部分,每部分的价值之和相等。但他们很快意识到有可能不存在这样的分法(即使大理石的价值之和是偶数)。例如,如果大理石的价值分别是1,1,3,4,4,就不可能被分为总价值相等的两部分。因此,他们请你写一个程序,判断是否存在公平的分法。
Input
输入包含多组数据。
每组数据由1行,包含6个正整数n1~n6,其中ni是价值为i的大理石数量。因此题目描述中的例子可以被表示为"1 0 1 2 0 0"。大理石的总数不超过20000.
Output
对第k组数据,输出一行"Collection #k:",再输出一行"Can be divided."或"Can't be divided.",然后再输出一个空行。
Sample Input
1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
Sample Output
Collection #1:
Can't be divided.
Collection #2:
Can be divided.
Solution
思路
其实考场的时候我对于我自己的想法十分的窒息,我竟然用贪心?很鬼畜啊,这果然不是我...
然后这道题目显然一眼看得出,是多重背包,然后看到背包就知道不用二进制肯定过不了,然后果断写上二进制,然后就切了.
Remind
特别注意多组数据注意清零数组...(我最近的操作真是令人绝望)
Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define ll long long
#define re register
inline int gi(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
int n,a[7],dp[1000010],t[1000010];
int main(){
n=6;int k=0;
while(1){
memset(dp,0,sizeof(dp));
int sum=0;
for(re int i=1;i<=n;i++){a[i]=gi();sum+=i*a[i];}
if(sum==0)break;
printf("Collection #%d:\n",++k);
if(sum%2)puts("Can't be divided.");
else{
int count=0;
for(re int i=1;i<=n;i++){
int k=1,weight=a[i];
while(k<=weight){
t[++count]=i*k;
weight-=k;k<<=1;
}
t[++count]=i*weight;
}
sum/=2;
for(re int i=1;i<=count;i++)
for(re int j=sum;j>=t[i];j--)
dp[j]=max(dp[j],dp[j-t[i]]+t[i]);
if(dp[sum]==sum)puts("Can be divided.");
else puts("Can't be divided.");
}
puts("");
}
return 0;
}