题目链接:http://acm.tju.edu.cn/toj/showp1034.html
题目大意:给定一些物品 每种物品都有其价值和数量, 问能否将他们分成价值相等的两堆。
思路:(一)、DP 多重背包;
(二)、DFS;
附:背包九讲程序课件:http://www.t00y.com/file/29938948
关于背包问题的好的总结博客:http://blog.csdn.net/accry/article/details/6250330 http://www.cnblogs.com/xiaofanke/archive/2012/08/22/2651043.html
代码:
(一)多重背包解:
//dp 多重背包问题
#include <iostream>
#include <cstring>
using namespace std;
int a[10];
int dp[120100];//dp[i]表示容量为i的背包能否被装满,如果容量为sum/2的背包能被装满,则说明可以分为两堆
int main()
{
int i,j;
int cas = 0;
while(++cas)
{
int sum = 0;
for(i=1;i<=6;i++)
{
cin>>a[i];
sum+=a[i]*i;
}
if(sum==0) break;
memset(dp,0,sizeof(dp));
cout<<"Collection #"<<cas<<":"<<endl;
if(sum%2==1)
{
cout<<"Can't be divided."<<endl;
cout<<endl;
continue;
}
dp[0]=1;
int used[120100];//used[j]表示容量为j时用去的背包数目
for(int i=1;i<=6;++i)
{
memset(used,0,sizeof(used));
for(j=i;j<=sum/2;j++)
{
if(!dp[j]&&dp[j-i]&&used[j-i]<a[i])
{
used[j] = used[j-i]+1;
dp[j] =1;
}
}
}
if(dp[sum/2])
cout<<"Can be divided."<<endl;
else
cout<<"Can't be divided."<<endl;
cout<<endl;
}
return 0;
}
(2)DFS解:
#include <iostream>
using namespace std;
int a[7],sum,half,flag;
void dfs(int value, int n)
{
int i;
if(flag) return;
if(value==half)
{
flag = 1;
return;
}
for(i=n;i>=1;i--)
{
if(a[i]!=0)
{
if(value+i<=half)
{
a[i]--;
dfs(value+i,i);
if(flag) break;
}
}
}
return;
}
int main()
{
int i;
int cas = 0;
while(++cas)
{
sum = 0;
for(i=1;i<=6;i++)
{
cin>>a[i];
sum+=a[i]*i;
}
if(sum==0) break;
if(sum%2)
{
cout<<"Collection #"<<cas<<":"<<endl;
cout<<"Can't be divided."<<endl<<endl;
continue;
}
half = sum/2;
flag = 0;
dfs(0,6);
if(flag)
{
cout<<"Collection #"<<cas<<":"<<endl;
cout<<"Can be divided."<<endl<<endl;
continue;
}
else
{
cout<<"Collection #"<<cas<<":"<<endl;
cout<<"Can't be divided."<<endl<<endl;
continue;
}
}
return 0;
}