【NOIP1999】邮票面值设计

来源:互联网 发布:c语言的sleep函数 编辑:程序博客网 时间:2024/04/29 06:29

【codevs 1047】
1047 邮票面值设计 1999年NOIP全国联赛提高组
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题解
题目描述 Description

给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1~MAX之间的每一个邮资值都能得到。

例如,N=3,K=2,如果面值分别为1分、4分,则在1分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分);如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到的连续的邮资最大值,所以MAX=7,面值分别为1分、3分。

输入描述 Input Description
N和K

输出描述 Output Description
每种邮票的面值,连续最大能到的面值数。数据保证答案唯一。

样例输入 Sample Input
3 2

样例输出 Sample Output
1 3

MAX=7

数据范围及提示 Data Size & Hint

最大&&连续面值
反正1肯定得选

对于下一张邮票,至少得比现在这张大
假设面值为x
保证连续最多到x
[x + 1,n * x + 1]

选择邮票?
下界是上一张邮票的面值+1
上界是当前能达到的最大邮票面值+1

如果现在连续最大是maxn 选择maxn+2 就会出现面值为maxn+1的断层
所以不能选择大于maxn+1的面值作为上界

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define MAXN 100005#define INF 2147483645#define max(a,b)(a > b ? a : b)int n,k,maxn = 0,cnt;int ca[55],sa[55],sum[MAXN];void dfs(int x){    if(x == k)    {        sum[0] = 0;        int now = 0;        while(sum[now] <= n)        {            now ++;            sum[now] = INF;            for(int i = 1; i <= k && sa[i] <= now; i ++)                sum[now] = min(sum[now],sum[now - sa[i]] + 1);        }           now --;        if(now > maxn)        {            maxn = now;            for(int i = 1; i <= k; i ++)                ca[i] = sa[i];        }        return;    }    int l = sa[x] + 1;    int r = sa[x] * n + 1;    for(int i = l; i <= r; i ++)        sa[x + 1] = i,dfs(x + 1);}int main(){    memset(sa,0,sizeof(sa));    memset(ca,0,sizeof(ca));    memset(sum,0,sizeof(sum));    scanf("%d %d",&n,&k);    sa[1] = 1;    dfs(1);    for(int i = 1; i <= k; i ++)        printf("%d ",ca[i]);    cout << endl;    cout << "MAX=" << maxn << endl;    return 0;}
0 0
原创粉丝点击