任务描述
本关任务:Marsha
和Bill
收藏了一批大理石。他们想要在他们之间分割收藏的大理石,使得他俩拥有相等的大理石份额。如果所有的大理石的价值相同,那么就很容易,因为他们只要将他们的收藏一分为二就可以了。但不幸的是,一些大理石比较大,或者比其他的大理石更漂亮。所以,Marsha
和Bill
开始给每块大理石赋一个值,一个在1
与6
之间的自然数。现在他们想平分这些大理石,使每个人得到总价值相同。但不幸的是,他们意识到,以这种方式划分大理石是不可能的(即使所有的大理石的总价值是偶数)。例如,如果有一块大理石的价值为1
,一块大理石的价值为3
,两块大理石的价值为4
,那么它们不可能被分成具有相等的价值的大理石集合。因此,他们要求您写一个程序,确定是否有一个公平划分大理石的方法。
编程要求
根据提示,在右侧编辑器补充代码。
测试说明
输入描述: 在输入的每一行描述一个要被分割的大理石的集合。行中包含六个非负整数n1,...,n6
,其中ni
是价值为i
的大理石的数目。所以,从上述的例子可以用行"1 0 1 2 0 0"
描述。大理石价值的总数不超过20000
。 输入文件的最后一行是"0 0 0 0 0 0"
;程序不必处理这一行。
输出描述: 对于每个集合,输出"Collection #k:"
,其中k是测试用例的编号,然后输出"Can be divided."
或"Can't be divided."
。 在每个测试用例后,输出一空行。
平台会对你编写的代码进行测试:
测试输入: 1 0 1 2 0 0
1 0 0 0 1 1
0 0 0 0 0 0
预期输出: Collection #1:
Can't be divided.
Collection #2:
Can be divided.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3+10;
const ll mod = 1e9+7;
const int inf = 0x7FFFFFFF;
int a[7];
int dp[1000000];
void solve(){
int sum = 0;
for(int i = 1;i <= 6;i++){
sum += i*a[i];
}
if(sum%2){
printf("Can't be divided.\n");
return;
}
int n = sum/2;
for(int i = 0;i <= n;i++){
dp[i] = -inf;
}
dp[0] = 0;
for(int i = 1;i <= 6;i++){
int num = min(a[i],n/i);
for(int k = 1;num > 0;k <<= 1){
if(k > num) k = num;
num -= k;
for(int j = n;j >= i*k;j--){
dp[j] = max(dp[j],dp[j-i*k]+i*k);
}
}
}
if(dp[n] == n){
printf("Can be divided.\n");
}else printf("Can't be divided.\n");
}
int main(){
int cnt = 1;
while(scanf("%d%d%d%d%d%d",&a[1],&a[2],&a[3],&a[4],&a[5],&a[6])&&a[1]+a[2]+a[3]+a[4]+a[5]+a[6]){
printf("Collection #%d:\n",cnt++);
solve();
cout<<endl;
}
return 0;
}