P1021
[NOIP1999 提高组] 邮票面值设计
题目描述
给定一个信封,最多只允许粘贴 \(N\) 张邮票,计算在给定 \(K\)(\(N+K \le 15\))种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值 \(MAX\),使在 \(1\) 至 \(MAX\) 之间的每一个邮资值都能得到。
例如,\(N=3\),\(K=2\),如果面值分别为 \(1\) 分、\(4\) 分,则在 \(1\sim 6\) 分之间的每一个邮资值都能得到(当然还有 \(8\) 分、\(9\) 分和 \(12\) 分);如果面值分别为 \(1\) 分、\(3\) 分,则在 \(1\sim 7\) 分之间的每一个邮资值都能得到。可以验证当 \(N=3\),\(K=2\) 时,\(7\) 分就是可以得到的连续的邮资最大值,所以 \(MAX=7\),面值分别为 \(1\) 分、\(3\) 分。
输入格式
\(2\) 个整数,代表 \(N\),\(K\)。
输出格式
输出共 \(2\) 行。
第一行输出若干个数字,表示选择的面值,从小到大排序。
第二行,输出 MAX=S,\(S\) 表示最大的面值。
样例 #1
样例输入 #1
3 2
样例输出 #1
1 3
MAX=7
搜索+DP
我们需要搜索K种邮票的面值分别为多少
然后在check答案时用DP
要加一些信仰剪枝? 开O2?
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k,jl[25],f[415],maxx,ans[25],tim=0;
void dfs(int step,int pre)
{
tim++;
if(step==k+1)
{
memset(f,0x3f,sizeof(f));
long long INF=f[0];
f[0]=0,f[1]=1;
for(int i=1;i<=k;i++)
for(int j=jl[i];j<=200;j++)
f[j]=min(f[j],f[j-jl[i]]+1);
int pos;
for(int i=1;i<=200;i++)
if(f[i]==INF||f[i]>n)
{
pos=i-1;
break;
}
if(pos>maxx)
{
maxx=pos;
for(int i=1;i<=k;i++)ans[i]=jl[i];
}
return ;
}
if(tim>5e7)return ;
for(int i=pre+1;i<=60;i++)
{
jl[step]=i;
dfs(step+1,i);
jl[step]=0;
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
jl[1]=1;
dfs(2,1);
for(int i=1;i<=k;i++)
cout<<ans[i]<<" ";cout<<"\n";
cout<<"MAX="<<maxx<<"\n";
return 0;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号