題目描述
給定一個信封,最多隻允許粘貼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;
}