1. 程式人生 > >洛谷1021 郵票面值設計 搜索

洛谷1021 郵票面值設計 搜索

style 背包 mem c++ %d 描述 log 數量 cnblogs

問題描述

給定一個信封,最多只允許粘貼N張郵票,計算在給定K(N+K≤15)種郵票的情況下(假定所有的郵票數量都足夠),如何設計郵票的面值,能得到最大值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分。

搜索題

單調搜索郵票的面值,每次背包找出f[i]為當郵資值為i用的最少的郵票數

#include<bits/stdc++.h>
using
namespace std; int a[17],ans[17]; int n,mx,k; int f[50005]; int dp(int x,int mxx){ memset(f,127,sizeof f); f[0]=0; for(int i=1;i<=x;i++){ for(int j=a[i];j<=a[x]*n;j++){ f[j]=min(f[j],f[j-a[i]]+1); } } for(int i=1;i<=a[x]*n;i++){
if(f[i]>n)return i-1; } return a[x]*n; } void dfs(int x,int an){ if(x==k+1){ if(an>mx){ mx=an; for(int i=1;i<=k;i++){ ans[i]=a[i]; } } return ; } for(int i=a[x-1]+1;i<=an+1;i++){ //
繼續找:為了避免重復,下一張郵票要比上一張郵票大,所以上邊界是a[t-1]+1,同時它不能比最大連續值+1還大,不然最大連續值的下一個數就永遠連不起來了 a[x]=i; int p=dp(x,an); //動歸尋找此時的最大連續數 dfs(x+1,p); } } int main(){ cin>>n>>k; dfs(1,0); for(int i=1;i<=k;i++)printf("%d ",ans[i]); printf("\n"); printf("MAX=%d",mx); return 0; }

洛谷1021 郵票面值設計 搜索