洛谷1021 邮票面值设计 搜索

问题描述

给定一个信封,最多只允许粘贴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("
");
    printf("MAX=%d",mx);
    return 0;
}
原文地址:https://www.cnblogs.com/Elfish/p/7642590.html