UVa 165 - Stamps(连续邮资问题)
来源:互联网 发布:officeim网络办公 编辑:程序博客网 时间:2024/06/07 03:36
题意:
某国家发行k种不同面值的邮票,并且规定每张信封上最多只能贴h张邮票。 公式n(h,k)表示用从k中面值的邮票中选择h张邮票,可以组成面额为连续的1,2,3,……n, n是能达到的最大面值之和。
例如当h=3,k=2时, 假设两种面值取值为1,4, 那么它们能组成连续的1……6, 虽然也可以组成8,9,12,但是它们是不连续的了。
解析:
首先开一个数组
stampVal[1...i] 来保存各个面值,再开一个maxVal[1...i] 来保存当前所有面值能组成的最大连续面值。
那么,我们可以确定stampVal[1] 一定是等于1的。因为如果没有1的话,很多数字都不能凑成。
然后相应的,maxVal[1]=1∗h
h为允许贴邮票的数量接下去就是确定第二个,第三个……第k个邮票的面值了,这个该怎么确定呢?
对于stampVal[i+1],它的取值范围是stampVal[i]+1 maxVal[i]+1
stampVal[i]+1 好理解, 这一次取的面值肯定要比上一次的面值大, 而这次取的面值的上限是上次能达到的最大连续面值+1, 是因为如果比这个更大的话, 那么就会出现断层, 即无法组成上次最大面值+1这个数了。 举个例子, 假设可以贴3张邮票,有3种面值,前面2种面值已经确定为1,2, 能达到的最大连续面值为6, 那么接下去第3种面值的取值范围为3~7。如果取得比7更大的话会怎样呢? 动手算下就知道了,假设取8的话, 那么面值为1,2,8,将无法组合出7 !知道了这个以后,就可以知道回溯的大概思路了, 但是还不够, 怎样取得给定的几个面值能够达到的最大连续面值呢?
最直观容易想到的就是直接递归回溯枚举所有情况, 便可知道最大连续值了。
这是查询的函数
//pos表示当前的位置,sum表示面额的和,num表示当前的面额数void check(int pos, int sum, int num) { if(pos >= h) { vis[sum] = true; return; } vis[sum] = true; for(int i = 1; i <= num; i++) check(pos+1, sum+stampVal[i], num);}
vis是一个全局数组, 调用递归时先初始化为0。然后用它来记录出现过的面值之和。
最后只需要从vis数组的下标1开始枚举,直到不是true值时就是能达到的最大连续面值。
AC代码
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 200;const int INF = 0x3f3f3f3f;bool vis[N];int ans[N], stampVal[N], maxVal[N], maxAns;int h, K;void check(int pos, int sum, int num) { if(pos >= h) { vis[sum] = true; return; } vis[sum] = true; for(int i = 1; i <= num; i++) check(pos+1, sum+stampVal[i], num);}void dfs(int curKind) { if(curKind >= K) { if(maxVal[curKind] > maxAns) { maxAns = maxVal[curKind]; memcpy(ans, stampVal, sizeof(stampVal)); } return; } for(int i = stampVal[curKind]+1; i <= maxVal[curKind]+1; i++) { memset(vis, false, sizeof(vis)); stampVal[curKind+1] = i; check(0, 0, curKind+1); int cnt = 0; while(vis[cnt]) {cnt++;} maxVal[curKind+1] = cnt-1; dfs(curKind+1); }}int main() { while(scanf("%d%d", &h, &K) != EOF && (h || K)) { stampVal[1] = 1; maxVal[1] = h; maxAns = -INF; dfs(1); for(int i = 1; i <= K; i++) { printf("%3d", ans[i]); } printf(" ->%3d\n", maxAns); } return 0;}
以上题解转自
http://blog.csdn.net/shuangde800 , By D_Double
- UVa 165 - Stamps(连续邮资问题)
- UVa 165 - Stamps, 连续邮资问题
- uva--165(邮资问题,dp)
- 连续邮资问题(回溯+动态规划)
- 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- UVA165连续邮资问题
- 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- 算法 连续邮资问题
- 连续邮资问题
- 连续邮资问题
- ScrollView起始位置不是最顶部
- 作业3.1
- 集合类说明及区别
- MapReduce开发中需要注意的几个问题
- 带输入框的UIAlertView
- UVa 165 - Stamps(连续邮资问题)
- ubuntu下使用android studio
- Java 反射详解
- 软件设计工具
- android listview 设置某些按键不可单击
- WebView 使用JS遇到的问题
- 在App层实现虚拟按键消息发送
- (poj3107Godfather,树形dp,next数组)树的重心
- android布局方式之FrameLayout