您的位置:首页 > 其它

UVA165

2014-08-12 10:47 183 查看
连续邮资问题,题目的意思就是你可以贴h张邮票,并且可供选择的面额有k种。k + h 《= 9;问连续面额最多有多少。。

样例3 2

指可以贴三张,有两种面额,面额是1 4的话,可以组成1,2.3,4,5,6,8,9,12,连续的最大到6个,而面额是 1 ,3时,可以组成 1,2,3,4,5,6,7,9连续的最大到7个。

我们要做的就是找到面额为多少时,连续的最大,最大为多少。

做法是用一个数组stamp 来存面额是多少,然后用数组m[ i ] 来存,当面额数为 i 时 最大连续到几。。

现在开始分析:

首先可以确定,第一种面额一定是 1 ,没有 1 很多数都凑不出来,不能连续。那么只有这一种面额时,最大连续到 h ,这很好理解,h张全是1 ,当然那 m [ 0 ] 也就是h了;

那么第二种面额该选哪个? 可以循环遍历,但题目没有给出限制,总不能从1试到无穷大。

现在m数组就用上了,第 i 张的面额大小范围就是从前一张大小加1(这点很明确) ,到m [ i ] 为止 。为什么呢,可以试想,如果你前面两张最多连续到了6了,比如是1 2,可以组成 1,2,3,4,5, 6。那么第三张最多也只能是7 ,因为如果第三张是8 ,你前两张最多到 6,那你还有可能组成7 吗? 所以就断了,这也是m数组记录前n张最多组成连续到几的目的。

现在要对每一种面额数量进行dfs(),为了得出每一种面额数量连续的最大值,当然最后结果只要取 m [ k - 1]即可,前面的递归是为了求出每一次循环的范围。。

#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;

const int N = 200;
int h, k;
int res
, stamp
, m
;
int fina;
bool flag
;

void dfs(int cur, int n, int sum){
if(cur >= h){
flag[sum] = true;
return;
}
flag[sum] = true;
for(int i = 0; i <= n; i++){
dfs(cur+1, n, sum+stamp[i]);
}
}

void search(int cur){
if(cur >= k){
if(m[cur-1] > fina){
fina = m[cur-1];
memcpy(res, stamp, sizeof(stamp));
}
return ;
}
for (int i = stamp[cur - 1] + 1; i <= m[cur - 1] + 1; i++){
memset(flag, 0, sizeof(flag));
stamp[cur] = i;
dfs(0, cur, 0);
int num = 0;
int j = 1;
while(flag[j++])
num++;
m[cur] = num;
search(cur+1);
}
}

int main(){
while(scanf("%d %d", &h, &k), h+k){
stamp[0] = 1;
m[0] = h;
fina = -1;
search(1);
for(int i = 0; i < k; i++)
printf("%3d", res[i]);
printf(" ->%3d\n", fina);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: