2.暴搜(枚举)
/* dfs:注意剪枝 */ #include<stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <map> using namespace std; int stamp_val[100]; // stamp_val[i]=j:第i类邮票的面额是j int request[100]; // request[i]=j:第i位顾客的需求是j int best_ans[5]; // 记录最佳答案 int curr_ans[5]; // 记录当前答案 bool visited[100]; // 访问标志 int max_types; // 最大类型数 int min_stamp_num; // 最少张数 int highest_val; // 最大面额 bool isTie; // tie标志 int stamp_num; // 邮票总数, stamp_val数组的长度 // 更新最优解 void updateBest() { for (int i=1; i<=4; i++) { best_ans[i] = curr_ans[i]; } } /* curr_stamp_num:当前的邮票张数 curr_types:当前的邮票类型数 curr_highest:当前的最大面额 start:从第start个类型的邮票开始搜索 curr:当前已选所有邮票的总面额 request:客户输入的面额 */ void dfs(int curr_stamp_num,int curr_types,int curr_highest,int start,int curr,int request) { // 判断是否出现了最优解 if (curr == request) { if (max_types < curr_types) { max_types = curr_types; min_stamp_num = curr_stamp_num; highest_val = curr_highest; isTie=false; updateBest(); } else if (max_types == curr_types) { if (min_stamp_num > curr_stamp_num) { min_stamp_num = curr_stamp_num; highest_val = curr_highest; isTie=false; updateBest(); } else if (min_stamp_num == curr_stamp_num) { if (highest_val < curr_highest) { highest_val = curr_highest; isTie=false; updateBest(); } else if (highest_val == curr_highest) { isTie = true; } } } return ; } // 已四张,返回 if (curr_stamp_num == 4) { return; } /* 此处为何从start而不是0开始搜索? 1.避免重复,如 1 1 2 同 1 2 1在数值上是相同的 2.更重要的是:从0开始是错误的! 回溯结束时,节点i被置为false,那么搜索i+1时如果仍从0开始搜索,会误认为i未访问过,因此,类型数会误加1 */ for (int i=start; i<stamp_num; i++) { if (stamp_val[i] >0 && curr+stamp_val[i] <= request) { curr_ans[curr_stamp_num+1]=stamp_val[i]; if (visited[i]) { visited[i] = true; dfs(curr_stamp_num+1,curr_types,stamp_val[i],i,curr+stamp_val[i],request); } else { visited[i] = true; dfs(curr_stamp_num+1,curr_types+1,stamp_val[i],i,curr+stamp_val[i],request); } visited[i] = false; curr_ans[curr_stamp_num+1]=0; } } } int main() { int tmp; while (scanf("%d",&tmp)!=EOF) { int stamp_value; stamp_num = 1; int req; int customer_num = 0; memset(stamp_val,0,sizeof(int)); memset(request,0,sizeof(int)); memset(best_ans,0,sizeof(int)); memset(curr_ans,0,sizeof(int)); memset(visited,false,sizeof(bool)); stamp_val[0] = tmp; while (scanf("%d",&stamp_value)) { if (stamp_value == 0) { break; } stamp_val[stamp_num++] = stamp_value; } while(scanf("%d",&req)) { if (req == 0) { break; } request[customer_num++] = req; } sort(stamp_val,stamp_val+stamp_num); for (int i=0; i<customer_num; i++) { max_types = 0; isTie = false; min_stamp_num = 0; if (stamp_val[stamp_num-1]*4 >= request[i] && stamp_val[0] <= request[i]) { dfs(0,0,0,0,0,request[i]); } printf("%d ",request[i]); if (max_types == 0) { printf("---- none\n"); } else if (isTie) { printf("(%d): tie\n",max_types); } else { sort(best_ans,best_ans+5); printf("(%d):",max_types); for (int j=1; j<=4; j++) { if (best_ans[j] == 0) { continue; } printf(" %d",best_ans[j]); } printf("\n"); } } } }
/* 枚举/暴搜:注意剪枝,如果面值相同的邮票超过5枚,其它的"剪掉" */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #include <map> using namespace std; int cmp(const void* a,const void* b) { return (int*)a - (int*)b; } struct ANS { int types; int num ; int max_value ; int stamps[30]; }; int stamps[100]; int request[100]; // 获取类型数 int get_types(int a, int b, int c, int d) { map<int,int> mp; mp[a]++; mp[b]++; mp[c]++; mp[d]++; mp.erase(0); return mp.size(); } int main() { int tmp; while (scanf("%d",&tmp)!=EOF) { int stamp_num,req,stamp_value ; int customer_num = 1; memset(stamps,0,sizeof(stamps)); memset(request,0,sizeof(request)); stamps[1] = tmp; stamp_num = 2; map<int,int> mp; mp[tmp]++; while(scanf("%d",&stamp_value)) { if (stamp_value == 0) { break; } mp[stamp_value]++; // if the number of the stamps which have the same value is more than 5,then do not put it into stamps arrays. if (mp[stamp_value] < 6) { stamps[stamp_num++] = stamp_value; } } while(scanf("%d",&req)) { if (req == 0) { break; } request[customer_num++] = req; } qsort(stamps,stamp_num,sizeof(int),cmp); // for each person int curr; for (int i=1; i<customer_num; i++) { // curr = 0; ANS tmp_ans; ANS best_ans = {0,0,0,{0,0,0,0,0}}; bool tier = false; // the fist stamp for (int j=0; j<stamp_num; j++) { // the second stamp for (int k=j; k<stamp_num; k++) { // the third stamp for (int l=k; l<stamp_num; l++) { // the forth stamp for (int m=l; m<stamp_num; m++) { curr = stamps[j] + stamps[k] + stamps[l] + stamps[m]; if (curr > request[i]) { break; } else if (curr == request[i]) { tmp_ans.max_value = max(max(stamps[j],stamps[k]),max(stamps[l],stamps[m])); tmp_ans.types = get_types(j,k,l,m); int cnt=1; if (stamps[j] != 0) { tmp_ans.stamps[cnt++] = stamps[j]; } if (stamps[k] != 0) { tmp_ans.stamps[cnt++] = stamps[k]; } if (stamps[l] != 0) { tmp_ans.stamps[cnt++] = stamps[l]; } if (stamps[m] != 0) { tmp_ans.stamps[cnt++] = stamps[m]; } tmp_ans.num = cnt-1; // compare the tmp answer with the current best answer bool flag = false; if (tmp_ans.types > best_ans.types) { flag = true; tier = false; } else if (tmp_ans.types == best_ans.types) { if (tmp_ans.num < best_ans.num) { flag = true; tier = false; } else if (tmp_ans.num == best_ans.num) { if (tmp_ans.max_value > best_ans.max_value) { flag = true; tier = false; } else if (tmp_ans.max_value == best_ans.max_value) { tier = true; } } } // update the best answer if (flag) { best_ans.num = tmp_ans.num; best_ans.types = tmp_ans.types; best_ans.max_value = tmp_ans.max_value; for (int ii=1; ii<=best_ans.num; ii++) { best_ans.stamps[ii] = tmp_ans.stamps[ii]; } } } } } } } // output the answer printf("%d ",request[i]); if (best_ans.num == 0) { printf("---- none\n"); } else if (tier) { printf("(%d): tie\n",best_ans.types); } else { sort(best_ans.stamps,best_ans.stamps+5); printf("(%d):",best_ans.types); for (int j=1; j<=4; j++) { if (best_ans.stamps[j] == 0) { continue; } printf(" %d",best_ans.stamps[j]); } printf("\n"); } } } }