题意:没看懂。
给出n种邮票,每种邮票有自己的面值(面值可能重复)
指定m种“总面值”,对每种“总面值”,求解满足如下条件的组合以达到该“总面值”
(1) 所用邮票在n种中可以重复选取
(2) 所用邮票张数〈=4
(3) 尽量多的使用那个不同种类的邮票 Max (Stamp Types)
(4) 若有多种方案满足(3),则选取张数最小的一种方案 Min (Stamp Num)
(5) 若有多种方案满足(3)(4),则选取“最大面额”最高的一种方案。 Max(Heightest Value)
(6) 若有多种方案满足(3)(4)(5) 则输出 “tie” 。
想法:深搜遍历所有的情况,注意题中的条件关系。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define inf 0x7fffffff using namespace std; int val[100+5],cust[100+5]; int val_num,ansnum; int now[5],ans[5]; int a,fuck; int len,vis[100+5]; int cal(int p[],int l) { memset(vis,0,sizeof(vis)); int sum=0; for(int i=0;i<l;i++) { if(!vis[p[i]]) { vis[p[i]]=1; sum++; } } return sum; } int getmax(int p[],int l) { int MAX=-1; for(int i=0;i<l;i++) { if(MAX<val[p[i]]) { MAX=val[p[i]]; } } return MAX; } void updata() { int nowk=cal(now,len); int ansk=cal(ans,ansnum); int ansmax=getmax(ans,ansnum); int nowmax=getmax(now,len); if(ansnum==-1||nowk>ansk||(nowk==ansk&&len<ansnum)||(nowk==ansk&&len==ansnum&&nowmax>ansmax)) { fuck=1; for(int i=0;i<len;i++) { ans[i]=now[i]; } ansnum=len; return; } if(nowk==ansk&&len==ansnum&&nowmax==ansmax) { fuck++; } } void dfs(int pos,int nows) { if(nows>a) return; if(nows==a) { updata(); } if(len==4) return;//KEY for(int i=pos;i<val_num;i++) { now[len]=i; len++; dfs(i,nows+val[i]); len--; } } void Input() { val_num=0; for(int i=1;;i++) { int c; scanf("%d",&c); if(!c) { val_num=i; break; } val[i]=c; } sort(val,val+val_num); } void Output() { int ansk=cal(ans,ansnum); if(!fuck) printf("%d ---- none\n",a); else if(fuck>1) printf("%d (%d): tie\n",a,ansk); else { sort(ans,ans+ansnum); printf("%d (%d):",a,ansk); for(int i=0;i<ansnum;i++) { printf(" %d",val[ans[i]]); } printf("\n"); } } void treatment() { for(int i=0;;i++) { fuck=0; len=0; memset(ans,0,sizeof(ans)); ansnum=-1; scanf("%d",&a); if(!a) break; dfs(0,0); Output(); } } int main() { while(~scanf("%d",&val[0])) { Input(); treatment(); } return 0; }