poj 1010 深搜
题意:第一行数字是邮票的面值,每一个数字就是一个不同的种类,哪怕面值相同。第二行数字是顾客所需要的邮票总面值。每个数字就是一个顾客的需求。顾客是集邮爱好者,所以必须尽可能的给他不同种类的邮票。但是一位顾客最多只能拿4张邮票。
满足顾客需求的解就是可行解。
邮票种类最多的可行解为最优。
如果存在两个以上的最优解的邮票种类是一样的,张数最少的更优
张数也一样的话,这些最优解中最大面值较大的更优。
若邮票种类、张数、最大面值三者都分别相同,则认为这些最优解相同,输出tie。
没有解就是none。
分析:1、最多拿四张邮票,如果同一面值的邮票种类超过5,以5计算。为什么不以4计算呢,因为tie。
2、若DFS的深度超过了4,那么就返回。(最多四张邮票)
3、先对输入的邮票按面值升序排序,DFS到面值k时,不再搜索面值<k的邮票。同时排序也是为了保证DFS的最优解的邮票种类最多。
#define N 100 int type[N],tPos; int now[4],nPos; int best[4],bPos; int need,sum; int kind,num,Max; int nkind,nnum,nMax; int n,flag; void gengxin() { int i; nkind=1; nnum=0; nMax=0; for(i=0;i<4;i++) { if(now[i]==-1) break; else { nnum++; if(type[now[i]]>nMax) nMax=type[now[i]]; if(i>0&&now[i]!=now[i-1]) nkind++; } } if(nkind>kind||(nkind==kind&&nnum<num)||(nkind==kind&&nnum==num&&nMax>Max)) { flag=1; bPos=i; kind=nkind; num=nnum; Max=nMax; for(int j=0;j<i;j++) best[j]=type[now[j]]; } else if(nkind==kind&&nnum==num&&nMax==Max) flag=2; } void solve() { if(tPos>=n||nPos>=4) return; now[nPos]=tPos; sum+=type[tPos]; nPos++; if(sum==need) gengxin(); else if(sum<need) solve(); nPos--; sum-=type[tPos]; now[nPos]=-1; tPos++; solve(); tPos--; } void quchong() { for(int i=0;i<n-5;i++) if(type[i]==type[i+5]) { int j=i+5,cnt=1; while(type[j]==type[j+1]) { j++; cnt++; } for(j=i+5;j+cnt<n;j++) type[j]=type[j+cnt]; i+=4; n-=cnt; } } void readData() { int i=0; while(cin>>type[i]) { if(type[i]==0) break; i++; } sort(type,type+i); n=i; quchong(); } void init() { tPos=nPos=bPos=flag=sum=0; kind=num=Max=0; for(int i=0;i<4;i++) best[i]=now[i]=-1; } void shuchu() { if(flag==0) cout<<need<<" ---- none"<<endl; else if(flag==1) { cout<<need<<" ("<<kind<<"): "; for(int i=0;i<bPos;i++) { if(i==bPos-1) cout<<best[i]; else cout<<best[i]<<' '; } cout<<endl; } else cout<<need<<" ("<<kind<<"): tie"<<endl; } int main(){ while(cin){ readData(); while(cin>>need&&need!=0){ init(); solve(); shuchu(); } } return 0; }