hdu1709

/*
分析:
    简单题。
    当年做这个题的时候,不仅用了母函数,还对母函数进行了一定的
拓展,不过最后还是觉得麻烦,就搁那儿了-、-I。今儿再一看,不久是
简单递推么。
    打两个hash,hash[i]代表i的重量是否可以称得,由于砝码是可以
两边放的,所以对以前已经可以达到的状态而言,由这个状态可以推出
两个状态,既分别把新的砝码放在左边、右边,判断推出的两个状态以
前是否已经退出来过了,推出来过了就不用理它了,否则把它标记一下。
说的不是老清楚,看代码吧。。。


                                                                      2012-12-03




*/








#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#include"math.h"
int n,up;
int w[111];
int c1[10011],c2[10011];
int main()
{
	int i,l;
	int tot,ans;
	while(scanf("%d",&n)!=-1)
	{
		tot=0;
		for(i=0;i<n;i++)	{scanf("%d",&w[i]);tot+=w[i];}

		memset(c1,0,sizeof(c1));
		memset(c2,0,sizeof(c2));
		up=0;
		c1[0]=c2[0]=1;
		for(i=0;i<n;i++)
		{
			for(l=0;l<=up;l++)
			{
				if(!c1[l])	continue;
				if(!c2[l+w[i]])
				{
					c2[l+w[i]]=1;
					if(l+w[i]>up)		up=l+w[i];
				}
				if(!c2[abs(l-w[i])])
				{
					c2[(abs(l-w[i]))]=1;
					if(abs(l-w[i])>up)	up=abs(l-w[i]);
				}
			}
			for(l=0;l<=up;l++)	c1[l]=c2[l];
		}

		ans=0;
		for(l=1;l<=up;l++)	if(c1[l])	ans++;
		if(ans>=tot)	printf("0\n");
		else
		{
			printf("%d\n",tot-ans);
			for(l=1;l<=tot;l++)	if(!c1[l])	{printf("%d",l);break;}
			for(l++;l<=tot;l++)	if(!c1[l])	printf(" %d",l);
			printf("\n");
		}
	}
	return 0;
}


你可能感兴趣的:(hdu1709)