1. 程式人生 > >CODEVS 1047 郵票面值設計

CODEVS 1047 郵票面值設計

數量 per 計算 ostream 答案 背包 row 提高 ane

1047 郵票面值設計

1999年NOIP全國聯賽提高組

時間限制: 1 s 空間限制: 128000 KB 題目等級 : 鉆石 Diamond
題目描述 Description

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

例如,N=3,K=2,如果面值分別為1分、4分,則在1分~6分之間的每一個郵資值都能得到(當然還有8分、9分和12分);如果面值分別為1分、3分,則在1分~7分之間的每一個郵資值都能得到。可以驗證當N=3,K=2時,7分就是可以得到的連續的郵資最大值,所以MAX=7,面值分別為1分、3分。

輸入描述 Input Description

N和K

輸出描述 Output Description

每種郵票的面值,連續最大能到的面值數。數據保證答案唯一。

樣例輸入 Sample Input

3 2

樣例輸出 Sample Output

1 3

MAX=7

思路:

先用dfs+剪枝找出所以符合要求的郵票種類,再用dp(01背包)。

看代碼:

#include <iostream>
#include <algorithm>
using namespace std;
int n,k,maxn=0;
int num[41],dp[4000001],ans[41];
void dpf(){
int t=0;
dp[0]=0;
while(dp[t]<=n){
t++;
dp[t]=41;
for(int j=1;j<=k&&t>=num[j];j++){
dp[t]=min(dp[t],dp[t-num[j]]+1);
}
}
cout<<t<<endl;
if(t-1>maxn){
maxn=t-1;
int i;
for(i=1;i<=k;i++)
ans[i]=num[i];
}
}
void dfs(int l){
if(l-1==k){
dpf();
return;
}
int i;
for(i=num[l-1]+1;i<=num[l-1]*n+1;i++){
num[l]=i;
dfs(l+1);
}
}
int main(){
num[1]=1;
cin>>n>>k;
dfs(2);
int i;
for(i=1;i<=k;i++){
if(i==k) cout<<ans[i]<<endl;
else cout<<ans[i]<<" ";
}
cout<<"MAX="<<maxn<<endl;
}

CODEVS 1047 郵票面值設計