完善程序 提高篇 9.[NOIP2007提高组](连续邮资问题)

文章介绍了一个关于邮票面值设计的问题,目标是使用不超过m张邮票表示连续整数集合的最大值。提供了一个递归回溯的C++程序来寻找最优解,程序涉及变量定义、回溯函数和主函数,通过不断调整邮票面值实现最大值最大化。
摘要由CSDN通过智能技术生成
/*
9.[NOIP2007提高组](连续邮资问题)
某国发行了n 种不同面值的邮票,并规定每封信最多允许贴m 张邮票,在这
些约束下,为了能贴出{1,2,3,…,maxvalue}连续整数集合的所有邮资,并使maxvalue 的值最
大,应该如何设计各邮票的面值?例如,当n=5、m=4 时,面值设计为{1,3,11,15,32},可使
maxvalue 达到最大值70(或者说,用这些面值的1 至4 张邮票可以表示不超过70 的所有邮资,但无
法表示邮资71。而用其他面值的1 至4 张邮票如果可以表示不超过k 的所有邮资,必有k≤70)。
下面是用递归回溯求解连续邮资问题的程序。数组x[1:n]表示n 种不同的邮票面值,并约定各元
素按下标是严格递增的。数组 bestx [1:n]存放使maxvalue 达到最大值的邮票面值(最优解),
数组y[maxl]用于记录当前已选定的邮票面值x[1:i]能贴出的各种邮资所需的最少邮票张数。请将程
序补充完整。
*/
#include <iostream.h>
#define NN 20
#define maxint 30000
#define maxl 500
int n,m,bestx[NN],x[NN],y[maxl],maxvalue=0;
void result()
{
	int j;
	cout<<"r="<<maxvalue<<endl;
	for(j=1;j<=n;j++)
		cout<<bestx[j]<<" ";
	cout <<endl;
}
void backtrace(int i,int r)
{ 
	int j,k,z[maxl];

	for(j=0;j<=①;j++)
		if(y[j]<m)
			for(k=1;k<=m-y[j];k++)
				if(y[j]+k<=y[ ②])
					y[ ③]=y[j]+k;

	while(y[r]<maxint) r++;
	if(i>n)
	{
		if(r-1>maxvalue)
		{
			maxvalue=④;
			for(j=1;j<=n;j++) bestx[j]=x[j];
		}
		return;
	}
	for(k=0;k<maxl;k++)
		z[k]=y[k];
	for(j=⑤;j<=r;j++)
	{
		x[i]=j;
		⑥ ;
		for(k=0;k<maxl;k++)	y[k]=z[k];
	}
}
void main()
{
	int j;
	cout<<"input n,m:"<<endl; cin >>n>>m;
	for(j=1;j<maxl;j++)
		y[j]=maxint;
	y[0]=0; x[0]=0; x[1]=1;
	backtrace(2,1);
	result();
	return 0;
}
/*
(1)、x[i-2]*(m-1) 
(2)、j+x[i-1]*k
(3)、j+x[i-1]*k
(4)、r-1
(5)、x[i-1]+1
(6)、backtrace(i+1,r) 
*/

 


 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dllglvzhenfeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值