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;
}
posted @ 2023-01-13 15:39  PKU_IMCOMING  阅读(15)  评论(0)    收藏  举报