标签: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; }
标签:bsp memset c++ main 情况下 搜索 设计 计算 pre
原文地址:http://www.cnblogs.com/Elfish/p/7642590.html