poj1010
来源:互联网 发布:张曼玉 知乎 编辑:程序博客网 时间:2024/05/01 04:39
Description
You have been hired by the Ruritanian Postal Service (RPS) to design their new postage software. The software allocates stamps to customers based on customer needs and the denominations that are currently in stock.
Ruritania is filled with people who correspond with stamp collectors. As a service to these people, the RPS asks that all stamp allocations have the maximum number of different types of stamps in it. In fact, the RPS has been known to issue several stamps of the same denomination in order to please customers (these count as different types, even though they are the same denomination). The maximum number of different types of stamps issued at any time is twenty-five.
To save money, the RPS would like to issue as few duplicate stamps as possible (given the constraint that they want to issue as many different types). Further, the RPS won't sell more than four stamps at a time.
Input
1 2 3 0 ; three different stamp types
7 4 0 ; two customers
1 1 0 ; a new set of stamps (two of the same type)
6 2 3 0 ; three customers
Note: the comments in this example are *not* part of the data file; data files contain only integers.
Output
The "best" combination is defined as the maximum number of different stamp types. In case of a tie, the combination with the fewest total stamps is best. If still tied, the set with the highest single-value stamp is best. If there is still a tie, print "tie".
For the sample input file, the output should be:
7 (3): 1 1 2 3
4 (2): 1 3
6 ---- none
2 (2): 1 1
3 (2): tie
That is, you should print the customer request, the number of types sold and the actual stamps. In case of no legal allocation, the line should look like it does in the example, with four hyphens after a space. In the case of a tie, still print the number of types but do not print the allocation (again, as in the example).Don't print extra blank at the end of each line.
Sample Input
1 2 3 0; three different stamp types7 4 0; two customers1 1 0; a new set of stamps (two of the same type)6 2 3 0; three customers
Sample Output
7 (3): 1 1 2 3 4 (2): 1 3 6 ---- none2 (2): 1 13 (2): tie
背景真复杂。
举个例子
1 2 3 0是给你当前邮票的面值,
7 4 0这是有顾客想买,一个想买7块钱的邮票,另一个想买4块钱的邮票;
然后让你给出买邮票的方案。如果有多个方案,那么优先级如下:
1,种类最多
2,1条件相同,则个数最多
3,1,2条件相同,则最大面值大的那套方案
4,1,2,3都相同,那就是tie
5,如果没有方案就输出none
常用方法是dfs遍历所有情况,找出最优。
中间有剪枝方案就是在试过1, 1, 1, 3这种情况以后,不试1, 1, 2, 1,直接试1, 1, 2, 2,因为有1的情况已经包含在之前的遍历里面了。
想起来很好想,但是写起来我还是无从下手的感觉。于是又网上查资料,查到一位,看他的代码反反复复看了N遍,最后发现这是我学长,现在已经本科毕业工作了,再看看这还是我老乡。哈哈,这么多巧合啊!
这是他的代码:
#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; }
这个代码能过,但是我感觉在更新函数里面,判断句
if (ansnum==-1|| know> kans|| (know == kans&& ansnum> total)||(kans== know && ansnum == total&& maxnow> maxans))应该是ansnum<total时才更新数据,total是当前得出的,如果当前的比原来的多才会更新的。
还有就是对tie情况的处理
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和2不同,所以tie应该为false,但是如果2和3相同,tie就会被修改为true,但是tie应该是指所有的可行方案都相同才是tie,而不是局部相同。
当然了,我的代码虽说 是一步一步按照学长写的,还花了整整一天时间,可还是没过。做到最后我做不下去了。因为不懂题目中给两个1是什么意思。如果是不同种类同面值,那么2的组合就是1 1,不是tie。那么3的组合也应该是1 1 1,不是tie,因为这是两种。但是题目给出的输出显然不是这样……
我的代码:
#include <stdio.h>#include <stdlib.h>#include <string.h>int value[300], customer_value, result[4]={-1}, none_mark=0, tie_mark=1, value_num=0, now[4]={-1}, total=0, result_num = -1;bool states[300];int getkinds(int *tmp, int num){int n = 0;memset( states, 0, sizeof(states));for(int i=0; i<num; i++){if( !states[tmp[i]] ){n++;states[tmp[i]] = true;}}return n;}int getmax( int *tmp, int num){int max = 0;for(int i=0; i < num; i++){if(value[tmp[i]] > max) max = value[tmp[i]];}return max;}void print(){if(none_mark == 1){printf("%d (%d):", customer_value, result_num);if(tie_mark == 1) printf("tie\n");else{for(int i=0; i<result_num; i++)printf(" %d", value[result[i]]);}printf("\n");}else{printf("%d ---- none\n", customer_value);}}void workout(){int result_kinds = getkinds( result, result_num);int now_kinds = getkinds(now, total);int result_max = getmax( result, result_num);int now_max = getmax(now, total);int mm = 0;if(result_num == -1) mm = 1;if(result_num == -1 || result_kinds <now_kinds || (result_kinds == now_kinds && total > result_num) || (result_kinds == now_kinds && total && now_max > result_max) ){if( mm == 0 ) tie_mark = 0;result_num = total;for(int i=0; i<total; i++){result[i] = now[i];}}}void dfs(int nn, int stamps_sum){if(stamps_sum > customer_value) return;if(stamps_sum == customer_value){none_mark = 1;workout();}if( total == 4) return;for(int i = nn; i<=value_num; i++){now[total++] = i;dfs( i, stamps_sum + value[i]);total--;}}int main(){int i=0, tmp_value, flag=1;while(flag){while(1){if( scanf("%d", &tmp_value) == EOF) {flag = 0;break;}if(tmp_value == 0) break;else value[i++]=tmp_value;}value_num = i-1;while(1){scanf("%d",&customer_value);if(customer_value != 0){dfs( 0 , 0 );print();}else break;}i=0;memset(result, -1, sizeof(result));none_mark = 0;tie_mark = 1;result_num = -1;total = 0;}return 0;}
- poj1010
- poj1010
- poj1010
- poj1010
- poj1010-STAMPS
- poj1010 暴搜
- poj1010搜索
- poj1010 枚举
- POJ1010 Stamps
- poj1010 dfs
- POJ1010(dfs)
- 【poj1010】 STAMPS
- POJ1010解题报告
- POJ1010-搜索题基础
- poj1010 STAMPS 简单搜索
- poj1010的问题分析
- POJ1010 STAMPS(DFS+剪枝)
- 【DFS】Poj1010 STAMPS
- 使用OpenSSL编程的基本方法
- 开启设计模式的大门
- C/C++与MFC数据类型转换
- MFC简单数据类型类及其转换
- Android开发真苦逼 因碎片化购400款手机
- poj1010
- XP CPU经常莫名其妙60%-70%,HDTune检测无坏块,System Interrupts进程异常问题解决
- 关于LocalSessionFactoryBean
- 《大话数据结构》--学习笔记3
- Baidu 网盘 邀请码 分享
- MySQL创建用户与授权
- 工作中应该注意的那么几小点
- iptv
- 如何在15分钟内掌握JavaScript面向对象编程