您的位置:首页 > 其它

【NOIP1999】邮票面值设计

2016-11-14 17:30 253 查看
【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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: