您的位置:首页 > 其它

pku acm 1010

2011-10-08 21:24 204 查看
参考了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;   //判断是否有tie

int 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: