这道题主要还是二分比较重要,否则TLE
<span style="background-color: rgb(0, 0, 0);"><span style="color:#ffffff;">#include<stdio.h>
#include<string.h>
int dp[100000];
int v[7];
int main()
{
int cas=0;
while(scanf("%d%d%d%d%d%d",&v[1],&v[2],&v[3],&v[4],&v[5],&v[6])!=EOF)
{
cas++;
if(!v[1]&&!v[2]&&!v[3]&&!v[4]&&!v[5]&&!v[6])
{
break;
}
int sum=v[1]+2*v[2]+3*v[3]+4*v[4]+5*v[5]+6*v[6];
printf("Collection #%d:\n",cas);
if(sum%2==1)
{
puts("Can't be divided.");
puts("");
continue;
}
int tmp=sum/2;
memset(dp,0,sizeof(dp));
dp[0]=1;
int val;
for(int i=1;i<=6;i++)//价值
{//这后面的j*2相当于二分,把当前的数量看成两部分同时来处理,j++的话会有搜重复的,比如装了1个,剩余了3个和装了3个剩余了1个就重复了,那么比如我4能装,那么3也一定能装,所以*2不能装入背包之后,在判断剩余的部分能不能装入背包,tmp-能装入的,一定会比能到目前为止装入的大,又比tmp小,所以就保证了所有的都遍历过了
for(int j=1;j<=v[i];j*=2)//数量
{
val=j*i;
for(int k=tmp;k>=val;k--)
{
if(dp[k-val]!=0)
{
dp[k]=1;
}
}
v[i]-=j;
}
val=v[i]*i;//剩余的数量
for(int k=tmp;k>=val;k--)
{
if(dp[k-val]!=0)
{
dp[k]=1;
}
}
}
if(dp[tmp]==0)
{
puts("Can't be divided.");
}
else
{
puts("Can be divided.");
}
puts("");
}
}</span></span>