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;
}

 

posted @ 2013-06-20 19:30  心向往之  阅读(350)  评论(0编辑  收藏  举报