邮票面值设计
Posted lyxzhz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了邮票面值设计相关的知识,希望对你有一定的参考价值。
题目:
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
二个整数N,K。
Output
连续的邮资最大值
回溯搜索,DP
-
首先分析得出邮票面值中,肯定有1分
-
用a数组记录邮票面值,在DP中用b数组记录每种邮票面值所用的次数,x数组用于记录所更新的最优解
-
初值a[1]=1;
-
回溯
- 在js()函数中得到a数组中i-1种邮票面值连续的邮资最大值res
- 判断是否能更新
- 枚举从a[i-1]+1到res的邮票面值
void find(int i) int k,z; z=js(i-1); if (i>n) if (z-1>ans) ans=z-1; for (int j=1; j<=n; j++) x[j]=a[j]; return; for (k=z; k>=a[i-1]+1; k--) a[i]=k; find(i+1);
DP
- b数组初始化,赋上最大值
- a数组中第i种邮票面值的邮资数为1
- 从res=0开始枚举
- b[res]=min(b[res-a[i]]+1,b[res])
- 当b[res]超过最多能粘贴的邮票数时,退出循环
int js(int t) int i,res; for (i=1; i<=1000; i++) b[i]=1000000000; for (i=1; i<=t; i++) b[a[i]]=1; res=0; do res++; for (i=1; i<=t; i++) if (res>a[i] && b[res-a[i]]+1<b[res]) b[res]=b[res-a[i]]+1; while (b[res]<=m); return res;
代码
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; int m,n,ans,a[1005],b[1005],x[1005]; int js(int t) int i,res; for (i=1; i<=1000; i++) b[i]=1000000000; for (i=1; i<=t; i++) b[a[i]]=1; res=0; do res++; for (i=1; i<=t; i++) if (res>a[i] && b[res-a[i]]+1<b[res]) b[res]=b[res-a[i]]+1; while (b[res]<=m); return res; void find(int i) int k,z; z=js(i-1); if (i>n) if (z-1>ans) ans=z-1; for (int j=1; j<=n; j++) x[j]=a[j]; return; for (k=z; k>=a[i-1]+1; k--) a[i]=k; find(i+1); int main() scanf("%d%d",&m,&n); a[1]=1; find(2); for (int i=1; i<=n; i++) printf("%d ",x[i]); printf("\n"); printf("MAX=%d\n",ans); return 0;
以上是关于邮票面值设计的主要内容,如果未能解决你的问题,请参考以下文章