[洛谷]P1021 郵票面值設計 (#搜索+dp)

題目描述

給定一個信封,最多隻允許粘貼NN張郵票,計算在給定KK(N+K≤15N+K≤15)種郵票的情況下(假定所有的郵票數量都足夠),如何設計郵票的面值,能得到最大值MAXMAX,使在11至MAXMAX之間的每一個郵資值都能得到。

例如,N=3N=3,K=2K=2,如果面值分別爲11分、44分,則在11分~66分之間的每一個郵資值都能得到(當然還有88分、99分和1212分);如果面值分別爲11分、33分,則在11分~77分之間的每一個郵資值都能得到。可以驗證當N=3N=3,K=2K=2時,77分就是可以得到的連續的郵資最大值,所以MAX=7MAX=7,面值分別爲11分、33分。

輸入格式

22個整數,代表NN,KK。

輸出格式

22行。第一行若干個數字,表示選擇的面值,從小到大排序。

第二行,輸出“MAX=SMAX=S”,SS表示最大的面值。

輸入輸出樣例

輸入 #1複製

3 2

輸出 #1複製

1 3
MAX=7

思路

#include <stdio.h>
#include <iostream>
#include <memory.h>
#define inf 2e9+7
using namespace std;
int n,k,s,stamp[21],dp[21*21],maxn(-1),ans[21];
void dfs(int i)
{
	register int j;
	if(i>k)//如果最大面值超過k 
	{
		int maxx(0);//這個組合的最大面值 
		memset(dp,0,sizeof(dp));
		while(dp[maxx]<=n)//判斷郵票值能否爲maxx 
		{
			maxx++;
			dp[maxx]=inf;
			for(j=1;j<=k;j++)
			{
				if(maxx-stamp[j]<0) break;//如果一張郵票面值大於所求值的話(此時stamp一定單調遞增) ,就結束循環 
				dp[maxx]=min(dp[maxx],dp[maxx-stamp[j]]+1);//dp數組存儲達到一個面值所需要的最小的郵票數
			}
		}
		if(maxx-1>maxn)
		{
			for(j=1;j<=k;j++)
			{
				ans[j]=stamp[j];
			}
			maxn=maxx-1;
			return;
		}
	}
	else
	{
		for(j=stamp[i-1]+1;j<=stamp[i-1]*n+1;j++)//一張郵票可以貼m張,因此下一張郵票必須小於上一張*m+1 
		{
			stamp[i]=j;
			dfs(i+1);
		}
	}
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i;
	cin>>n>>k;
	stamp[1]=1;
	dfs(2);
	for(i=1;i<=k;i++)
	{
		cout<<ans[i]<<' ';
	}cout<<endl;
	cout<<"MAX="<<maxn<<endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章