pku acm 1010

来源:互联网 发布:nginx 支持websocket 编辑:程序博客网 时间:2024/06/05 14:08

参考了http://blog.csdn.net/huxin2007/article/details/6766074的文章。

类似于究举法。

主要思路:

1. 先对输入按面值的从小到大排序,这对剪枝有帮助,比如:

    输入面值:1,2,3,4,5        顾客要求是 3

    假如计算到分支 1,1,2 的时候,超过 3 了,后面的 1,1,3  ;  1,1,4  ;  1,1,5 都不需要计算了

2. 对解的评价,采用了一个计算公式,省去了较复杂的条件判断。--这个比较好

     评价分数 = 种类数 * 100 + (4 - 邮票数) * 10 + 最大面值;

#include <iostream>#include <algorithm>using namespace std;int stamps[100];    //存放邮票的种类(取25在poj上不能通过,在zoj上可以通过)int denomination;       //顾客要求的面值int nTypes;            //邮票种类数int result[4];    //存放最终结果int mresult[4];   //存放中间结果bool tie = false;   //判断是否有tieint score = 0;      //最优解的分数int cards = 0;      //最优解中有多少张邮票int kindsnum = 0;   //最优解中有多少种邮票int kinds[4];     //记录类型的数组void DFS(int sum, int index, int ccards/*当前解中有多少张邮票*/){    if((ccards > 3) && (sum != denomination))  return; //失败了,剪枝    if(sum == denomination)//成功了,开始评分    {        int ckindsnum = 1;//当前解中有多少种邮票        for(int i = 1; i < ccards; i++)        {            if(kinds[i] != kinds[i-1])                ckindsnum++;        }        int cscore = ckindsnum * 100 + (4 - ccards) * 10 + stamps[index];//当前解的评分        if(cscore == score)tie = true;                else if(cscore > score)        {            tie = false;            score = cscore;            cards = ccards;            kindsnum = ckindsnum;            for(int i = 0; i < 4; i++)                result[i] = mresult[i];        }        return;    }    for(int i = index; i < nTypes; ++i)    {        if(sum + stamps[i] > denomination)return;//剪枝        mresult[ccards] = stamps[i];        kinds[ccards] = i;        DFS(sum + stamps[i], i, ccards + 1);    }    return;}void Print(){if (score == 0){        cout << denomination << " ---- none" << endl;        return;    }    if(tie)    {        cout << denomination << " (" << kindsnum << "): tie" << endl;        return;    }    else    {        cout << denomination << " (" << kindsnum << "): ";        for(int i = 0; i < cards; i++)            cout << result[i] << " ";    }    cout << endl;}int main(){    freopen("in.txt", "rt", stdin);    //从0开始计数nTypes = 0;while(cin>>stamps[nTypes])    {        for (++nTypes; cin>>stamps[nTypes] && stamps[nTypes] != 0; ++nTypes);sort(stamps,stamps+nTypes);        while(cin>>denomination && denomination != 0){score = 0,tie = false;DFS(0,0,0);Print();}        nTypes = 0;}    return 0;}


原创粉丝点击