河南第五届ACM省赛(Divideing Jewels)

题目地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=546

思路:和杭电1171几乎一模一样,多重背包,题目说的是总价值不超过一万结果是不超过十万,老是RE,想死的心都有了,深搜也可以,懒得写了

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

const int inf = 0x7f7f7f7f;//2139062143
typedef long long ll;
using namespace std;

int dp[100010];
int a[15];
int sum;

void zeroone_pack(int value)
{
	for(int i=sum; i>=value; i--)
	{
		dp[i] = max(dp[i],dp[i-value] + value);
	}
}

void complete_pack(int value)
{
	for(int i=value; i<=sum; i++)
	{
		dp[i] = max(dp[i],dp[i-value] + value);
	}
}

void multi_pack()
{
	int i,count,k;
	for(i=1; i<=10; i++)
	{
	    if(a[i] == 0)
        {
            continue;
        }
		if(a[i] * i >= sum)
		{
			complete_pack(i);
		}
		else//转化为01背包
		{
			k = 1;
			count = a[i];
			while(k < count)
			{
				zeroone_pack(k*i);
				count -= k;
				k *= 2;
			}
			zeroone_pack(count*i);
		}
	}
}

int main()
{
    int i;
    int k = 1;
    while(true)
    {
        memset(dp,0,sizeof(dp));
        sum = 0;
        for(i=1; i<=10; i++)
        {
            scanf("%d",&a[i]);
            sum += i * a[i];
        }
        if(sum == 0)
        {
            break;
        }
        if(sum & 1)//位运算比取余运算快
        {
            printf("#%d:Can't be divided.\n\n",k++);
            continue;
        }
        sum /= 2;
        multi_pack();
        if(dp[sum] == sum)
        {
            printf("#%d:Can be divided.\n\n",k++);
        }
        else
        {
            printf("#%d:Can't be divided.\n\n",k++);
        }
    }
    return 0;
}


你可能感兴趣的:(河南第五届ACM省赛(Divideing Jewels))