Question:http://poj.org/problem?id=1010
问题点:DFS、剪枝。
1 Memory: 220K Time: 32MS
2 Language: C++ Result: Accepted
3
4 #include <iostream>
5 using namespace std;
6
7 #define MAX_STAMP_TYPE 100
8 int stamp[MAX_STAMP_TYPE];
9 bool tie,none;
10 int now[4],ans[4];//记录stamp的index
11 int max_stamp;//记录最大邮票
12 int getInfo(int sta[]){
13 int tmp_a,tmp_b,tmp_c;
14 tmp_a=1;
15 tmp_b=1;
16 tmp_c=sta[0];
17 for(int i=1;i<4 && sta[i]>0;i++)
18 {
19 if(sta[i-1]!=sta[i]) tmp_a++;//取种类数 千位
20 tmp_b++;//取总张数 百位
21 tmp_c=sta[i-1]>sta[i]?sta[i-1]:sta[i];//取最大值 十位和个位
22 }
23 return tmp_a*1000+(10-tmp_b)*100+tmp_c;
24 }
25 void compare(){
26 none=false;//只要有结果,none就置为false
27 int nowInfo=getInfo(now);
28 int ansInfo=getInfo(ans);
29 char r=nowInfo>ansInfo?'g':(nowInfo<ansInfo?'l':'e');//g:出现更优解 l:不如现有解 e:tie
30 if(r=='g'){//如果出现更优解,将now中的数据复制到ans中保存
31 memcpy(ans,now,sizeof(now));
32 tie=false;
33 }else if(r=='e'){
34 tie=true;
35 }
36 return;
37 }
38 void dfs(int num,int cnt){
39 if(num==0){//剩余数为0,即为解的出现条件
40 compare();
41 return;
42 }else if(cnt>=4){//邮票数不能大于4张
43 return;
44 }else if(num<0){//剩余需分配数不能小于0
45 return;
46 }else if(num>max_stamp*(4-cnt)){
47 return;
48 }
49 for(int i=(cnt>0?now[cnt-1]:1);i<=stamp[0];i++)
50 {
51 now[cnt]=i;
52 dfs(num-stamp[i],cnt+1);
53 now[cnt]=0;
54 }
55 }
56 int main()
57 {
58 do{
59 int tmp,i=1;
60 max_stamp=0;
61 memset(stamp,0,sizeof(stamp));
62 while(cin>>tmp && tmp!=0){
63 stamp[i++]=tmp;
64 max_stamp=max_stamp>tmp?max_stamp:tmp;
65 }
66 stamp[0]=i-1;//记录邮票种类数
67 while(cin>>tmp && tmp!=0){
68 tie=false;
69 none=true;
70 memset(now,0,sizeof(now));
71 memset(ans,0,sizeof(ans));
72 dfs(tmp,0);
73 if(tie){
74 cout<<tmp<<" ("<<getInfo(ans)/1000<<"): "<<"tie"<<endl;
75 }else if(none){
76 cout<<tmp<<" ---- none"<<endl;
77 }else{
78 cout<<tmp<<" ("<<getInfo(ans)/1000<<"):";
79 for(int i=0;i<4 && ans[i]>0;i++){
80 cout<<" "<<stamp[ans[i]];
81 }
82 cout<<endl;
83 }
84 }
85 }while(getchar()!=EOF);
86 return 0;
87 }