HDU 1059 Dividing 解题报告 多重背包

HDU 1059 Dividing 解题报告 多重背包

背包问题算法先放条链接在这:https://blog.csdn.net/LYHVOYAGE/article/details/8545852
这是我觉得写得最精简又好的博客了,其他博客太长,有不少还乱,讲的不清楚。
解题思路:多重背包+二进制优化。多重背包,其实就是把问题想办法分成01背包和完全背包,对于这题来说,某种marble如果都能多到超过目标量了,直接当完全背包用,如果不够,就把这种marble升级下,
按1, 2,3,4…个的方式捆绑,每种捆绑方式都当作一种新marble,且其数量只有1个,这样就变成了01背包问题,注意使用的marble不要超过原来marble的总数,二进制优化指3=2+1,5=4+1…所有数都能用二进制下的数加减得到,这样就省时间了。
在这里插入图片描述

#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<iomanip>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<stdio.h>
#include<cstdio>
#include<stdlib.h>
#include<fstream>
#include<iomanip>
#pragma warning(disable:4996)
#define INF 0x3f3f3f3f
#define ll long long
#define PI acos(-1.0)
const int N = 1000010;
const int maxn = 1e9;
using namespace std;
int a[7];
int dp[200005];
int aver, sum;
void zero(int cost)//01背包
{
	for (int i = aver; i >= cost; i--)
	{
		dp[i] = max(dp[i], dp[i - cost] + cost);
	}
}
void complet(int cost)//完全背包
{
	for (int i = cost; i <= aver; i++)
	{
		dp[i] = max(dp[i], dp[i - cost] + cost);
	}
}
void multi(int cost, int amount)//多重背包
{
	if (cost * amount >= aver)//如果i乘数量能超过或我们需要的总和aver,那么可以看成完全背包处理
	{
		complet(cost);
		return;
	}
	int k = 1;
	while (k < amount)
	{
		zero(k * cost);//把价值为i的marble拿k个捆一起当01背包用
		amount -= k;
		k *=2;//用k<<=1也可以。貌似k*=4也可以,因为3=1+2=1+1+1,把2漏了貌似也没事,还变快了。。
	}
	zero(amount * cost);
}
int main()
{
	int t = 0;
	while (scanf("%d%d%d%d%d%d", &a[1], &a[2], &a[3], &a[4], &a[5], &a[6]) != EOF)
	{
		memset(dp, 0, sizeof(dp));
		t++;
		if (a[1] == 0 && a[2] == 0 && a[3] == 0 && a[4] == 0 && a[5] == 0 && a[6] == 0)
			break;
		sum = 0;
		for (int i = 1; i <= 6; i++)
		{
			sum += i * a[i];
		}
		printf("Collection #%d:\n", t);
		if (sum % 2)//如果所有marble的value和已经是奇数,那么必然不可能分成两份完全一样的背包
		{
			printf("Can't be divided.\n\n");
			continue;
		}
		aver = sum / 2;//aver是背包的目标容量
		for (int i = 1; i <= 6; i++)
		{
			multi(i, a[i]);
		}
		if (dp[aver] == aver)
			printf("Can be divided.\n\n");
		else
			printf("Can't be divided.\n\n");
	}
}


发布了64 篇原创文章 · 获赞 0 · 访问量 1472

猜你喜欢

转载自blog.csdn.net/weixin_45566331/article/details/104224577