【解题报告】洛谷P1021 邮票面值设计

题目链接

https://www.luogu.com.cn/problem/P1021

思路

这道题目,首先要用固定的邮票数量和固定的种类表示出最大的数目以内的所有数字

所以我们就对其进行分析

首先1肯定要选,然后呢?

我们发现这个时候从1到n都能表示出来了,然后呢?

我们从1到n枚举选择第二种邮票,然后以此类推

直到找到可以表示总共最大的为止

这个时候呢我们就要用动态规划

我们记录一个 f[i]f[i] 表示选到了第 ii 张邮票,选多少个选到了这里

然后我们就进行动态规划就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
int n,k;
int a[20],ans[20];
int f[50005];
int mx=0;
int work(int x)
{
memset(f,0x3f3f3f,sizeof(f));
f[0]=0;
for(int i=1;i<=x;i++)
{
for(int j=a[i];j<=a[x]*n;j++)
{
if(f[j-a[i]]<n)
f[j]=min(f[j],f[j-a[i]]+1);
}
}
int sol=0;
while(f[sol]<=100)
sol++;
return sol;
}
void dfs(int x)
{
if(x==k+1)
{
int t=work(x-1);
if(t>mx)
{
mx=t;
memcpy(ans,a,sizeof(ans));
}
return ;
}
int end=work(x-1);
for(int i=a[x-1]+1;i<=end+1;i++)
{
a[x]=i;
dfs(x+1);
a[x]=0;//回溯
}
}
int main()
{
cin>>n>>k;
a[1]=1;
dfs(2);
for(int i=1;i<=k;i++)
cout<<ans[i]<<" ";
cout<<'\n';
cout<<"MAX="<<mx-1<<'\n';
return 0;
}