背包问题之0-1背包(三)

问题描述:有n个物品,第i个物品的重量为w[i],把n这n个物品分成两堆使两堆物品的差尽量小。
题目链接1:NYOJ题目325 Zb的生日           题目链接2:NYOJ题目456 邮票分你一半
解题思路:这个问题是0-1背包(一)的变形,假设sumn为n个物品重量总和则用0-1背包描述该问题为:有n个物品,第i个物品的重量为w[i],把这n个物品放入背包中在背包重量不超过sumn/2 的前提下,使背包重量尽可能大
源代码如下:

#include <stdio.h>
#include <string.h>
#define maxn 22
#define maxw 100001       //保证maxw>sumn/2
int w[maxn],f[maxw];

int main()
{
	int n,W,i,j,sumn;
	while(scanf("%d",&n)!=EOF)
	{
		memset(f,0,sizeof(f));
		for(sumn=0,i=1;i<=n;i++)
		{
			scanf("%d",w+i);
			sumn+=w[i];
		}
		W=sumn/2;
		for(i=1;i<=n;i++)
		{
			for(j=W;j>=w[i];j--)
				if(f[ j-w[i] ]+w[i]>f[j])
					f[j]=f[ j-w[i] ]+w[i];
		}
		
		printf("%d\n",sumn-2*f[W]);
	}

	return 0;
}


问题描述:有n个物品,第i个物品的重量为w[i],看能否把这n个物品分成总重量相等的两堆物品。
输入:多组测试数据以EOF结尾,第一行输入物品数量n (1 ≤ n ≤ 20),第二行有n个数,w1, …, wn (1 ≤ wi ≤ 10000)分别代表每个物品的重量。
输出:若能分成相等的两堆输出YES,否则输出NO,每组输出占一行。
解题思路:这个问题是0-1背包(二)的变形,假设sumn为n个物品重量总和则用0-1背包描述该问题为:有n个物品,第i个物品的重量为w[i],把这n个物品放入背包中使背包重量恰好为sumn/2。
源代码如下:

#include <stdio.h>
#include <string.h>
#define maxn 22
#define maxw 100001 
int w[maxn],f[maxw];

int main()
{
	int n,W,i,j,sumn;
	while(scanf("%d",&n)!=EOF)
	{
		memset(f,-1,sizeof(f));
		f[0]=0;
		for(sumn=0,i=1;i<=n;i++)
		{
			scanf("%d",w+i);
			sumn+=w[i];
		}
		if(sumn%2!=0)
		{
			printf("NO\n");
			continue;
		}
		else
		{
			W=sumn/2;
			for(i=1;i<=n;i++)
			{
				for(j=W;j>=w[i];j--)
					if(f[j-w[i]]!=-1&&f[ j-w[i] ]+w[i]>f[j])
						f[j]=f[ j-w[i] ]+w[i];
			}
			
			if(f[W]!=-1)
			 printf("YES\n");
			else
			 printf("NO\n");
		}
			
	}

	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值