类似于 1276
题意:给定若干个宝物,价值为1-6,每个宝物数量不一,能否均分成两个
解法:
统计总价值total,首先必须是偶数,然后总价值i * num(i)其中 (i= 1-6)
然后total / 2作为背包的体积,每个物品的价值作为体积,也作为价值,类似于poj 1276
但是,注意这个题的要求不一样,一定要拼出来最终答案
即滚动数组f[V] == V才可以,这跟要求f[V]最大不一样,具体不一样的地方在于初始化的时候
要求恰好装满背包,那么在初始化时除了f[0]为0其它f[1..V]均设为-∞,
这样就可以保证最终得到的f[N]是一种恰好装满背包的最优解。
另外题目中说 最多的数目为 20000 那么V 最大为 20000*6 / 2 =60000
maxn 设置数组开的不够大导致 RA一次
都是通过测试数据发现的问题,囧。。。
测试输入
1 0 1 2 0 0
1 0 0 0 1 1
2 0 0 3 0 0
1 1 1 1 1 1
0 6999 0 6001 0 7000
0 0 0 0 4 5
3333 3333 3333 3333 3333 3333
0 0 0 1 0 2
1 2 3 4 5 6
0 0 0 0 4 5
0 0 2 3 0 0
0 0 0 2 2 1
0 0 0 1 2 2
0 1 2 3 4 5
6 5 4 3 2 1
0 0 5 0 3 0
0 3 0 0 0 1
0 2 0 1 0 0
1 1 1 0 0 0
3334 3334 3333 3333 3333 3333
0 1 1 1 1 1
0 0 0 0 6 5
0 0 0 3 0 2
0 0 1 3 3 4
0 0 0 1 4 6
0 0 0 1 4 5
0 0 0 0 0 0
测试输出
Collection #1:
Can't be divided.
Collection #2:
Can be divided.
Collection #3:
Can't be divided.
Collection #4:
Can't be divided.
Collection #5:
Can't be divided.
Collection #6:
Can't be divided.
Collection #7:
Can't be divided.
Collection #8:
Can't be divided.
Collection #9:
Can't be divided.
Collection #10:
Can't be divided.
Collection #11:
Can't be divided.
Collection #12:
Can't be divided.
Collection #13:
Can't be divided.
Collection #14:
Can be divided.
Collection #15:
Can be divided.
Collection #16:
Can be divided.
Collection #17:
Can be divided.
Collection #18:
Can be divided.
Collection #19:
Can be divided.
Collection #20:
Can be divided.
Collection #21:
Can be divided.
Collection #22:
Can be divided.
Collection #23:
Can be divided.
Collection #24:
Can be divided.
Collection #25:
Can be divided.
Collection #26:
Can be divided.
代码:
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <queue>
using namespace std;
///宏定义
const int INF = 990000000;
const int maxn = 150000 ;
const int MAXN = maxn;
///全局变量 和 函数
int max(int a, int b)
{
return a > b ? a : b;
}
int N;
int V;
//int mnums[maxn];
//int mval[maxn];
int fee[maxn];
int nums[10];
int f[maxn];
int main()
{
///变量定义
int i, j, m;
int cases = 1;
while(1)
{
int totval = 0;
int V;
bool flag = false;
for (i = 1; i <= 6; i++)
{
scanf("%d", &nums[i]);
if (nums[i] != 0)
{
flag = true;
totval += i * nums[i];
}
}
if (!flag)
break;
printf("Collection #%d:\n", cases++);
if (totval % 2 != 0)
{
printf("Can't be divided.\n");
printf("\n");
continue;
}
else
V = totval / 2;
int cnt = 0;
for (int kk = 1; kk <= 6; kk++) //进行分组,存入fee数组
{
if (nums[kk] == 0)
continue;
int k = 0;
int temp = 1;
while (1)
{
if (temp - 1 >= nums[kk])
break;
temp *= 2;
k++;
}
k = k - 1;
//分组
int at = 1;
for (i = 0; i < k + 1; i++)
{
if (i != 0)
{
if (i == k)
{
at = nums[kk] - at * 2 + 1;
}
else
at *= 2;
}
fee[cnt++] = at * kk;
}
}
// memset(f, 0, sizeof(f));
//初始化f数组
for (i = 0; i <= V; i++) //初始化不正确WA一次,通过测试数据发现
//V上限可能超过 maxn RA一次,通过测试数据发现,对于f的访问越界改变了fee数组的值
// 数目最多20000个,所以值的上限可能很大
{
if (i == 0)
{
f[i] = 0;
}
else
f[i] = -INF;
}
//0-1背包经典求解
for (i = 0; i < cnt; i++)
{
for (j = V; j >= 0; j--)
{
if (j >= fee[i])
{
if (f[j - fee[i]] == -INF)
continue;
if (f[j] < f[j - fee[i]] + fee[i])
{
f[j] = f[j - fee[i]] + fee[i];
}
}
}
}
int ans = f[V];
if (ans == V)
{
printf("Can be divided.\n");
printf("\n");
}
else
{
printf("Can't be divided.\n");
printf("\n");
}
// printf("%d\n", ans);
}
///结束
return 0;
}