题目大意就是给定几个数据,这些数据之间可以进行加减运算,当然每个数据只能够用一次。开了一个数组来专门来存储标记负数。
母函数的关键就是在每次进行组合时,为了避免重复利用,所以在操作中,往往需要两个数组,一个用来存储当次的元素对于整个状态的影响,另一个则接收到当前元素为止,前面所有元素所组合成的状态,这也就是每次都是利用后者来判断能否形成组合,而且当每一个元素的更新结束后,后者需要吸收新出现的组合形式。
代码如下:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int b[210]; /* */ char hash[10010], hash2[10010], t[10010], t2[10010];
int cmp( const void *a, const void *b )
{
return *( int * )a- *( int * )b;
}
void weave( int N, int max )
{
memset( hash, 0, sizeof( hash ) );
memset( hash2, 0, sizeof( hash2 ) );
memset( t, 0, sizeof( t ) );
memset( t2, 0, sizeof( t2 ) );
hash[0]= 1;
hash2[0]= 1;
for( int i= 1; i<= N+ N; ++i ){
for( int k= 0; k<= max; ++k ){
if( hash[k]){
int c= b[i]+ k;
if( c> 0 ){
t[c]= 1;
}
else{
t2[-c]= 1;
}
}
if( hash2[k] ){
int c= b[i]- k;
if( c> 0 ){
t[c]= 1;
}
else{
t2[-c]= 1;
}
}
}
for( int i= 1; i<= max; ++i ){
hash[i]+= t[i];
hash2[i]+= t2[i];
t[i]= 0;
t2[i]= 0;
}
}
}
int main( )
{
int N;
while( scanf( "%d", &N )!= EOF ){
int max= 0;
for( int i= 1; i<= N+ N; i+= 2 ){
cin>> b[i];
b[i+ 1]= -b[i];
max+= b[i];
}
qsort( b+ 1, 2* N, sizeof( b[0] ), cmp );
weave( N, max );
int flag= 0, cnt= 0;
for( int i= 1; i<= max; ++i ){
if( !hash[i] ){
cnt++;
}
}
cout<< cnt<< endl;
if( cnt== 0 )
continue;
for( int i= 1; i<= max; ++i ){
if( !hash[i] ){
if( flag ){
cout<< " "<< i;
}
else{
cout<< i;
flag= 1;
}
}
}
cout<< endl;
}
}