UVA165

来源:互联网 发布:软件质量保证的过程 编辑:程序博客网 时间:2024/05/22 14:16

连续邮资问题,题目的意思就是你可以贴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[N], stamp[N], m[N];int fina;bool flag[N];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;}




0 0
原创粉丝点击