给你一些邮票的面值,然后给你一些顾客给出的价钱,求出邮票的组合来满足每一位顾客,要求是最多四张邮票,每张可以用多次(其实最多也就四次,因为要求最多四张,否则就是none)。
如:邮票面值1 2 3 0;0代表这行结束
顾客的需求:7 4 0
结果:
7 (3): 1 1 2 3
4 (2): 1 3
解释一下:
由于每次有多种组合,那么如何取结果呢?
如果这些组合都能满足用户的的需求,那么
1.选种类最多的
2.如果种类相同,选总数最多的
3.如果总数相同,选邮票值组合最大值最大的那一组
4.如果连最大值也相同,那么就是tie
5。如果没有这样的组合,也就是不能用4张以内的邮票满足顾客,那么就是none
输出格式,第一个是总价值,括号里面的是邮票的种类,后面是相应的值。
做过题目的一定知道小棍(sticks)那道题目,这道和那道差不多。深搜,由于最多四张邮票,所以相当于每张邮票最多用四次,将所有情况枚举出来,对于满足用户的进行比较,取出最优的,就是结果。
输入格式就不说了。
先说一下深搜函数:
void dfs(int nn, int ssum) { if (ssum > m) { return; } if (ssum == m) { none = false; comp(); } if (total == 4) { return; } for (int i = nn; i < n; i ++) { now[total] = i; total ++; dfs(i, ssum + stamps[i]); total --; } }
void comp() { int know = cal(now, total); int kans = cal(ans, ansnum); int maxans = getMax(ans, ansnum); int maxnow = getMax(now, total); if (ansnum == -1 || know > kans || (know == kans && ansnum > total) || (kans == know && ansnum == total && maxnow > maxans)) { tie = false; ansnum = total; for (int i = 0; i < total; i ++) { ans[i] = now[i]; } return; } if (kans == know && ansnum == total && maxnow == maxans) { tie = true; } }
1、将当前这种情况和原来的进行比较,如果种类多,或者数目多,或者最大值大,然后更新组合。否则就是tie。2、至于上面的cal函数就是计算当前有多少中邮票,getmax是获得邮票中的最大值。
总的代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; int stamps[300];//保存所有邮票值 int now[5];//当前组合 int ans[5];//最终结果组合 int n,m,total,ansnum;//总邮票数目,顾客需求以及组合邮票的数目 bool tie,none;//是否是平局还是没有这种组合 bool vis[300];//为了计算多少种邮票的标志数组 int cal(int tmp[], int num)//计算有多少种类邮票 { int res = 0; memset(vis, 0, sizeof(vis)); for (int i = 0; i < num; i ++) { if (!vis[tmp[i]]) { vis[tmp[i]] = true; res ++; } } return res; } int getMax(int tmp[], int num)//计算邮票中的最大值 { int res = 0; for (int i = 0; i < num; i ++) { if (res < stamps[tmp[i]]) { res = stamps[tmp[i]]; } } return res; } void comp()//更新邮票组合 { int know = cal(now, total); int kans = cal(ans, ansnum); int maxans = getMax(ans, ansnum); int maxnow = getMax(now, total); if (ansnum == -1 || know > kans || (know == kans && ansnum > total) || (kans == know && ansnum == total && maxnow > maxans)) { tie = false; ansnum = total; for (int i = 0; i < total; i ++) { ans[i] = now[i]; } return; } if (kans == know && ansnum == total && maxnow == maxans) { tie = true; } } void dfs(int nn, int ssum)//深搜,遍历每一种情况 { if (ssum > m) { return; } if (ssum == m) { none = false; comp(); } if (total == 4) { return; } for (int i = nn; i < n; i ++) { now[total] = i; total ++; dfs(i, ssum + stamps[i]); total --; } } void print()//输出格式 { if (none) { printf("%d ---- none\n", m); return; } printf("%d (%d):", m, cal(ans, ansnum)); if (tie) { printf(" tie\n"); return; } for (int i = 0; i < ansnum; i ++) { printf(" %d", stamps[ans[i]]); } printf("\n"); } int main()//主函数 { int i,j; while (scanf("%d", &j) != EOF) { i = 0; stamps[i] = j; while (stamps[i]) { i ++; scanf("%d", &stamps[i]); } n = i ; sort(stamps, stamps + n); while (scanf("%d" ,&m),m) { total = 0; ansnum = -1; tie = false; none = true; dfs(0, 0); if (!none) { sort(ans, ans + ansnum); } print(); } } return 0; }