问题描述:有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;
}