dfs 注意题目中的要求。满足顾客需求的解就是可行解。邮票种类最多的可行解为最优。如果存在两个以上的最优解的邮票种类是一样的,张数最少的更优张数也一样的话,这些最优解中最大面值较大的更优。若邮票种类、张数、最大面值三者都分别相同,则认为这些最优解相同,输出tie。没有解就是none。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[1000],type[1000],book[1000];
int customer,flag=0,flag_tie=0;
int solve[6];
int ans[6];
int max1(int *t){
int maxn=-1;
for(int i=2;i<6;i++){
if(maxn<t[i]){
maxn=t[i];
}
}
return maxn;
}
void update(int all_num,int type_num){
ans[0]=type_num;
ans[1]=all_num;
for(int i=2;i<all_num+2;i++){
ans[i]=solve[i-2];
}
}
int dfs(int cos,int all_num,int type_num,int pre){//当前邮票价值 邮票总数 邮票种类总数 前一个邮票编号(用于剪枝)
// cout<<cos<<' '<<all_num<<' '<<type_num<<endl;
if(all_num>=5) return 0;//最多有四张邮票
if(customer==cos){
if(!flag){
if(type_num==ans[0]){
if(all_num==ans[1]){
int maxn=max1(solve);
int maxn1=max1(ans);
if(maxn1==maxn){//最大面额相等
flag_tie=1;
}
else if(maxn>maxn1){//选择面额更大的
flag_tie=0;
update(all_num,type_num);
}
}
else if(all_num<ans[1]){//选择总数更少的
flag_tie=0;
update(all_num,type_num);
}
}
else if(type_num>ans[0]){//选择种类更多的
flag_tie=0;
update(all_num,type_num);
}
}
else{
flag=1;
update(all_num,type_num);
}
}
else if(cos>customer){
return 0;
}
for(int i=pre;a[i]!=0;i++){
if(cos+a[i]<=customer){
solve[all_num]=a[i];
if(book[i]==0){
book[i]++;
// cout<<cos<<' '<<a[i]<<endl;
dfs(cos+a[i],all_num+1,type_num+1,i);
// cout<<a[i+1]<<' '<<cos<<endl;
}
else{
book[i]++;
dfs(cos+a[i],all_num+1,type_num,i);
}
solve[all_num]=0;
book[i]--;
}
else {//之前排过序,所以若当前的不符合要求则不用继续搜
break;
}
}
}
int main(){
int i=0;
while(true){
int i;
for(i=0;;i++){
if(scanf("%d",&a[i])==EOF){
return 0;
};
if(a[i]==0){
break;
}
}
sort(a,a+i);
while(scanf("%d",&customer)&&customer){
memset(type,0,sizeof(type));
memset(book,0,sizeof(book));
memset(ans,0,sizeof(ans));
memset(solve,0,sizeof(solve));
dfs(0,0,0,0);
printf("%d",customer);
if(ans[1]==0){
printf(" ---- none\n");
}
else if(flag_tie){
printf(" (%d): tie\n",ans[0]);
}
else{
printf(" (%d):",ans[0]);
for(int i=2;i<ans[1]+2;i++){
printf(" %d",ans[i]);
}
printf("\n");
}
}
}
}