今天总算是碰到一道复杂题了。。。(我BT了?)
弄死我了,主要是排除重复情况,我想不通,最后参考了前人的代码,修改后AC了。。。
思路:通过递归,得出可能存在的解法,并记录,查找原记录,若存在相同则取消记录
#include <iostream>
#include <vector>
#include <string>
#include <stdlib.h>
using namespace std;
int sum;
int sticknum;
int stick[20];
int mark[20];
int solution;
int sols[100][20]; //记录不重复的答案
int slen[100]; //记录第j组答案的长度
int solnum; //记录不重复的答案的数量
void compute(int start,int cursum){
for(int i=start;i<sticknum;i++){
if(mark[i]==0&&stick[i]<=cursum){
mark[i]=1;
int tmp=cursum-stick[i];
if(tmp==0){
int tt=0;
for(int j=0;j<sticknum;j++){
if(mark[j]==1){
sols[solnum][tt++]=stick[j];
}
}
if(solution==0){ //如果是第一组答案,就直接记录
slen[solnum]=tt;
solution++;
solnum++;
mark[i]=0;
}else{
bool test=false;
for(int k=0;k<solnum&&!test;k++){ //判断答案是否重复,如果重复就不对solnum加1,否则加1,
if(slen[k]==tt){ //先判断这两组组答案的长度是否相等,不等就直接判断下一组。
for(int m=0;m<tt;m++){
if(sols[k][m]!=sols[solnum][m])
{
break;
}
if(m==tt-1)test=true; //表示答案完全匹配,这一组答案就可以舍掉了
}
}
}
if(!test){ //如果答案与前面的都不重复,就对solution+1,solnum+1,
solution++;
slen[solnum]=tt;
solnum++;
}
}
}else{
compute(i+1,tmp);
}
mark[i]=0;
}
}
}
int main()
{
while(1)
{
cin>>sum>>sticknum;
if(sum==0)break;
memset(stick,0,sizeof(stick));
memset(mark,0,sizeof(mark));
memset(sols,0,sizeof(sols));
memset(slen,0,sizeof(slen));
solution=0;
solnum=0;
for(int i=0;i<sticknum;i++){
cin>>stick[i];
}
cout<<"Sums of "<<sum<<":"<<endl;
compute(0,sum);
if(solution==0){
cout<<"NONE"<<endl;
}else{
for(int i=0;i<solnum;i++)
{
cout<<sols[i][0];
for(int j=1;j<slen[i];j++)
cout<<"+"<<sols[i][j];
cout<<endl;
}
}
}
}