您的位置:首页 > 其它

USACO section 2.2 Subset Sums(DP,背包)

2012-08-29 20:37 381 查看
SubsetSums
JRMFormanysetsofconsecutiveintegersfrom1throughN(1<=N<=39),onecanpartitionthesetintotwosetswhosesumsareidentical.

Forexample,ifN=3,onecanpartitiontheset{1,2,3}inonewaysothatthesumsofbothsubsetsareidentical:

{3}and{1,2}

Thiscountsasasinglepartitioning(i.e.,reversingtheordercountsasthesamepartitioningandthusdoesnotincreasethecountofpartitions).

IfN=7,therearefourwaystopartitiontheset{1,2,3,...7}sothateachpartitionhasthesamesum:

{1,6,7}and{2,3,4,5}
{2,5,7}and{1,3,4,6}
{3,4,7}and{1,2,5,6}
{1,2,4,7}and{3,5,6}

GivenN,yourprogramshouldprintthenumberofwaysasetcontainingtheintegersfrom1throughNcanbepartitionedintotwosetswhosesumsareidentical.Print0iftherearenosuchways.

Yourprogrammustcalculatetheanswer,notlookitupfromatable.

PROGRAMNAME:subset

INPUTFORMAT

TheinputfilecontainsasinglelinewithasingleintegerrepresentingN,asabove.

SAMPLEINPUT(filesubset.in)

[code]7

OUTPUTFORMAT

Theoutputfilecontainsasinglelinewithasingleintegerthattellshowmanysame-sumpartitionscanbemadefromtheset{1,2,...,N}.Theoutputfileshouldcontain0iftherearenowaystomakeasame-sumpartition.

SAMPLEOUTPUT(filesubset.out)

4


[/code]


具体看程序:



/*
ID:nealgav1
PROG:subset
LANG:C++
*/
#include<fstream>
#include<cstring>
usingnamespacestd;
constintmm=2300;
longlongf[60][mm];
longlongdp(intx,intc)
{memset(f,0,sizeof(f));
f[1][0]=1;f[1][1]=1;
for(inti=2;i<=x;i++)
for(intj=0;j<=c;j++)
if(j-i>=0)
f[i][j]=f[i-1][j]+f[i-1][j-i];
elsef[i][j]=f[i-1][j];
/**容量为j,个数为i的方法数有两种情况,一是个数为i-1,容量就已经是j了,这时不用
往里面放东西,另一种是当个数为i-1,容量为j-i;这时只要将个数i放入容量即为j;因此
f[i][j]=f[i-1][j]+f[i-1][j-i];*/
returnf[x][c];
}
intmain()
{ifstreamcin("subset.in");
ofstreamcout("subset.out");
intm,ans;
cin>>m;
ans=((1+m)*m)/2;
if(ans&1){cout<<"0\n";return0;}///当和为奇数时不可能
elseans/=2;
cout<<dp(m,ans)/2<<"\n";///答案是一半和容量的1/2.
}

[/code]





USER:NealGavinGavin[nealgav1]
TASK:subset
LANG:C++

Compiling...
Compile:OK

Executing...
Test1:TESTOK[0.000secs,4412KB]
Test2:TESTOK[0.000secs,4412KB]
Test3:TESTOK[0.011secs,4412KB]
Test4:TESTOK[0.011secs,4412KB]
Test5:TESTOK[0.011secs,4412KB]
Test6:TESTOK[0.011secs,4412KB]
Test7:TESTOK[0.000secs,4412KB]

AlltestsOK.
YOURPROGRAM('subset')WORKEDFIRSTTIME!That'sfantastic
--andararething.Pleaseacceptthesespecialautomated
congratulations.


Herearethetestdatainputs:

-------test1----
7
-------test2----
15
-------test3----
24-------test4----
31
-------test5----
36
-------test6----
39
-------test7----
37

Keepupthegoodwork!


Thanksforyoursubmission!

SubsetSumsRobKolstad

Thisisaclassicdynamicprogrammingproblem.Hal'ssolutionisshownbelow.

/*Calculatehowmanytwo-waypartitionsof{1,2,...,N}are
evensplits(thesumsoftheelementsofbothpartitionareequal)*/

#include<stdio.h>
#include<string.h>

#defineMAXSUM637

unsignedintnumsets[637][51];

intmax;
unsignedintsum;

main(intargc,char**argv)
{
intlv,lv2,lv3;
intcnt;
FILE*fin,*fout;

fin=fopen("subset.in","r");
fscanf(fin,"%d",&max);
fclose(fin);
fout=fopen("subset.out","w");

if((max%4)==1||(max%4)==2){
fprintf(stderr,"0\n");
exit(1);
}

sum=max*(max+1)/4;

memset(numsets,0,sizeof(numsets[0]));
numsets[0][0]=1;
for(lv=1;lv<max;lv++){
for(lv2=0;lv2<=sum;lv2++)
numsets[lv2][lv]=numsets[lv2][lv-1];
for(lv2=0;lv2<=sum-lv;lv2++)
numsets[lv2+lv][lv]+=numsets[lv2][lv-1];
}

fprintf(fout,"%u\n",numsets[sum][max-1]);
fclose(fout);
exit(0);
}


andhere'sanevenmoreconcisesolutionfromNickTomitovofBulgaria:

#include<fstream>
usingnamespacestd;
constunsignedintMAX_SUM=1024;
intn;
unsignedlonglongintdyn[MAX_SUM];
ifstreamfin("subset.in");
ofstreamfout("subset.out");

intmain(){
fin>>n;
fin.close();
ints=n*(n+1);
if(s%4){
fout<<0<<endl;
fout.close();
return;
}
s/=4;
inti,j;
dyn[0]=1;
for(i=1;i<=n;i++)
for(j=s;j>=i;j--)
dyn[j]+=dyn[j-i];
fout<<(dyn[s]/2)<<endl;
fout.close();
return0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: