背包水题 zoj3623 Poj1014&Zoj1149&Hdu1059 Hdu2844

zoj3623

题意:输入一个n和l,n代表n组值,l代表敌人的总权值,再输入n组值,每组两个数,分别代表制造这组战舰需要的时间和每秒钟可以对敌人造成伤害的权值,创建战舰可以重复创建。问需要多长时间,可以打败敌人。

思路:完全背包。

#include <cstdio>
#include <cstring>
#define max(x,y) ((x)>(y)?(x):(y))

const int INF=0x0fffffff;
int f[370],time[30],lenth[370];
int n,L;

void CompletePack ()
{
    for (int i=1;i<=n;i++)
        for (int j=0;j<330;j++)
            f[j+time[i]]=max(f[j+time[i]],f[j]+j*lenth[i]);
}

int main ()
{
    int i;
    while (~scanf("%d%d",&n,&L))
    {
        memset(f,0,sizeof(f));
        for (i=1;i<=n;i++)
            scanf("%d%d",&time[i],&lenth[i]);
        CompletePack ();
        for (i=1;i<=330;i++)
            if (f[i]>=L)
            {
                printf("%d\n",i);
                break;
            }
    }
    return 0;
}


Poj1014 & Zoj1149 & Hdu1059

题意:给你一堆石头,石头的价值有1,2,3,4,5,6(N=6)种,其对应的数量也给出,问能否实现平均分配?

思路:先求出总价值sum,如果奇数,显然不能,如果是偶数,多重背包

#include <cstdio>
#include <cstring>
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)

int n,sum,v;
int f[10000*6+5];

void ZeroOnePack (int cost, int weight)
{
    for (int j=v;j>=cost;j--)
        f[j] = max(f[j], f[j-cost] + weight);
}

void CompletePack (int cost, int weight)
{
    for (int j=cost;j<=v;j++)
        f[j] = max(f[j], f[j-cost] + weight);
}

void MultiplePack (int cost, int weight, int all)
{
    if (cost*all >= v)     //如果足够,转化为完全背包
    {
        CompletePack (cost, weight);
        return ;
    }
    int k=1;
    while (k < all)         //否则利用二进制的思想将其划分为若干个小物品
    {
        ZeroOnePack (k*cost, k*weight);
        all-=k;
        k<<=1;
    }
    ZeroOnePack (all*cost,all*weight);
}

int main()
{
    int cas=0;
    while (true)
    {
        cas++;
        int i;
        sum=0;
        int sumval=0;
        int num[10];
        memset(f,0,sizeof(f));
        for (i=1;i<=6;i++)
        {
            scanf("%d",&num[i]);
            sum+=num[i];
            sumval+=i*num[i];
        }
        if (sum==0)
            break;
        if (sumval%2==1)
        {
            printf("Collection #%d:\nCan't be divided.\n\n",cas);
            continue;
        }
        v=sumval/2;
        for (i=1;i<=6;i++)
            MultiplePack (i,i,num[i]);
        if (f[v]==sumval/2)
            printf("Collection #%d:\nCan be divided.\n",cas);
        else
            printf("Collection #%d:\nCan't be divided.\n",cas);
        printf("\n");
    }
    return 0;
}

Hdu2844

题意:求出硬币的组合方案,使得硬币的总价值不超过价值m

思路:多重背包

#include <cstdio>
#include <cstring>
#define max(x,y) (x)>(y)?(x):(y)
#define min(x,y) (x)<(y)?(x):(y)

const int INF=0x3fffffff;
int n,v;
int f[100005],a[105],c[105];

void ZeroOnePack (int cost, int weight)
{
	for (int j=v;j>=cost;j--)
		f[j] = max(f[j], f[j-cost] + weight);
}

void CompletePack (int cost, int weight)
{
	for (int j=cost;j<=v;j++)
		f[j] = max(f[j], f[j-cost] + weight);
}

void MultiplePack (int cost, int weight, int all)
{
	if (cost*all >= v)     //如果足够,转化为完全背包
	{
		CompletePack (cost, weight);
		return ;
	}
	int k=1;
	while (k < all)       //否则利用二进制的思想将其划分为若干个小物品
	{
		ZeroOnePack (k*cost, k*weight);
		all-=k;
		k<<=1;
	}
	ZeroOnePack (all*cost,all*weight);
}

int main()
{
	while (scanf("%d%d",&n,&v),n+v)
	{
		int i,ans=0;
		memset(f,0x8f,sizeof(f));   //赋值负无穷
//		for (i=1;i<v+5;i++)
//			f[i]=-INF;            
		f[0]=0;
		for (i=0;i<n;i++)
			scanf("%d",&a[i]);
		for (i=0;i<n;i++)
			scanf("%d",&c[i]);
		for (i=0;i<n;i++)
			MultiplePack (a[i],a[i],c[i]);
		for (i=1;i<=v;i++)
//			if (f[i]>0)    由恰好装满背包的性质这样也可以
			if (f[i]==i)
				ans++;
		printf("%d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值