/*
虽然也认同这题是基础的搜索题,但因做题太不熟练,写了好久~
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=4;
const int NN=1000;
int n,types,sum,maxz,a[NN],hash[NN],p[N],s[N];
bool tie;
void reanswer(int cnt,int _types){ //更新最优解
types=_types; sum=cnt; maxz=a[p[cnt-1]];
memcpy(s,p,sizeof(s));
tie=false;
}
void judge(int cnt,int _types){
if (_types>types) reanswer(cnt,_types); //按邮票种类
else if (_types==types){
if (cnt<sum) reanswer(cnt,_types); //按邮票数
else if (cnt==sum && a[p[cnt-1]]>maxz) reanswer(cnt,_types); //按邮票最大面值
else if (cnt==sum && a[p[cnt-1]]==maxz) tie=true; //这里写错了,debug了不少时间
}
}
void init(){
types=-1; sum=0; maxz=0; tie=false;
}
void dfs(int x,int k,int cnt,int _types){
if (x==0) { judge(cnt,_types); return; }
if (cnt==N || k==n || x>(N-cnt)*a[n-1]) return; //剪枝(1.数量已达4;2.邮票种类枚举完了;3.当前邮票组合过小,已明显不能组合成功)
int y=x;
for (int i=cnt; i<N && x>=a[k]; i++){ //枚举当前邮票的数量从1开始
x-=a[k];
p[i]=k;
dfs(x,k+1,i+1,_types+1);
}
dfs(y,k+1,cnt,_types); //当前邮票不用时
}
int main(){
int i,x;
while (!feof(stdin)){
memset(hash,0,sizeof(hash));
for (i=n=0;;i++,n++){
scanf("%d",&a[i]);
if (a[i]==0) break;
if (++hash[a[i]]>5) i--,n--; //去重,同面额的邮票保留最多5种即可
}
sort(a,a+n); //排序,一为之后的输出有序,二使得dfs能优先搜索到有效组合
while (scanf("%d",&x),x){
init();
dfs(x,0,0,0);
printf("%d ",x);
if (types==-1) printf("---- none\n"); //没有可用组合
else{
printf("(%d):",types);
if (tie) printf(" tie");
else for (int i=0; i<sum; i++) printf(" %d",a[s[i]]);
printf("\n");
}
}
}
return 0;
}
POJ1010-搜索题基础
最新推荐文章于 2020-01-27 10:07:07 发布