码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷1021 邮票面值设计 搜索

时间:2017-10-09 20:50:22      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:bsp   memset   c++   main   情况下   搜索   设计   计算   pre   

问题描述

给定一个信封,最多只允许粘贴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 邮票面值设计 搜索

标签:bsp   memset   c++   main   情况下   搜索   设计   计算   pre   

原文地址:http://www.cnblogs.com/Elfish/p/7642590.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!