【NOIP1999】邮票面值设计
时间限制: 1 Sec 内存限制: 64 MB提交: 131 解决: 63
[ 提交][ 状态][ 我的提交]
题目描述
给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1~MAX之间的每一个邮资值都能得到。
输入
第1行:2个整数N K
输出
第一行从小到大写出所用邮票面值,
第二行写"MAX="MAX
样例输入
(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
3 2
样例输出
1 3
MAX=7
提示
N=3,K=2,如果面值分别为1分、4分,则在1分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分);如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到的连续的邮资最大值,所以MAX=7,面值分别为1分、3分。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int N, K, Ans;
int A[42], Ansp[42], f[100000];
int DP_find(int x){//DP求出前x种邮票用去N张,达到f[i]所需最少数量
int i = 0;
while(f[i] <= N){
i++;
f[i] = 0x3f3f3f3f;
for(int j = 1; j <= x; j++) if(i >= A[j])
f[i] = min(f[i], f[i - A[j]] + 1);
}
return i - 1;
}
void Dfs(int x, int maxlast){//现在是第x种邮票,前x-1种邮票共用去N张能得到的最大值maxlast
if(x > K){
if(maxlast > Ans){
Ans = maxlast;
memcpy(Ansp, A, sizeof(A));
}
return ;
}
for(int i = A[x - 1] + 1; i <= maxlast + 1; i++){//第x种邮票的邮资大于第x-1张,为了保证能够集到连续邮资,第x种邮票的邮资不超过maxlast+1(想清楚为什么??)
A[x] = i;
Dfs(x + 1, DP_find(x));
}
}
int main(){
scanf("%d%d", &N, &K);
Dfs(1, 0);
printf("%d", Ansp[1]);
for(int i = 2; i <= K; i++)
printf(" %d", Ansp[i]);
putchar(10);
printf("MAX=%d\n", Ans);
return 0;
}