邮票问题--解决后给高分!

柯本 2001-09-13 11:26:36
加精

邮局发行一套有四种不同票面值的邮票,若每封信所贴的邮票张数不超过三枚,
存在整数R,使得用不超过三枚的邮票,可以贴出连续的整数1,2,3...R,
找出这四种面值数,使得R最大。


...全文
415 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
pl5th2001 2001-12-02
  • 打赏
  • 举报
回复
《软件技术基础》的《算法》中有该题的算法
happyer 2001-09-16
  • 打赏
  • 举报
回复
up
benny87 2001-09-15
  • 打赏
  • 举报
回复
up
lu_hm 2001-09-15
  • 打赏
  • 举报
回复
gz
柯本 2001-09-14
  • 打赏
  • 举报
回复
last up
柯本 2001-09-14
  • 打赏
  • 举报
回复
答案好象是对了
有无更好的算法?
分还可以加!
lu_hm 2001-09-14
  • 打赏
  • 举报
回复
int ok(int v[4],int m)
{
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
{
if ((m==v[i]) || (m==v[j]) || (m==v[k]))
return 1;
if ((m==v[i]+v[j]) || (m==v[i]+v[k]) || (m==v[j]+v[k]))
return 1;
if(v[i]+v[j]+v[k]==m)
return 1;
}
return -1;
}
const MAXVAL=39;
void __fastcall TForm1::Button2Click(TObject *Sender)
{
int v[4],m,maxm=1,mv[4];
String x;

v[0]=v[1]=v[2]=v[3]=1;
for(int i=1;i<MAXVAL;i++)
{
v[1]=i;
for(int j=i+1;j<MAXVAL;j++)
{
v[2]=j;
for(int k=j+1;k<MAXVAL;k++)
{
v[3]=k;
m=0 ;
while(1)
{
m++;
if (ok(v,m)==-1)
break;
}
m--;
if (m>maxm)
{
maxm=m;
mv[0]=v[0];
mv[1]=v[1];
mv[2]=v[2];
mv[3]=v[3];
}
}
}
}
x.printf("%d : %d %d %d %d",maxm,mv[0],mv[1],mv[2],mv[3]);
demo->Lines->Add(x);
}
//---------------------------------------------------------------------------
答案为:
1 4 7 8
wjzhuang 2001-09-14
  • 打赏
  • 举报
回复
好像我搞得太复杂了~~~~~~
gloom 2001-09-14
  • 打赏
  • 举报
回复
输出结果为1,4,7,8,最大值为24
gloom 2001-09-14
  • 打赏
  • 举报
回复
#include <iostream.h>
int max(int v1,int v2,int v3)//至少有一个参数为1,故只需三个参数
{
int max=0;
int flag=0;
for (max=2;1;max++)
{
flag=0;
for (int t1=0;t1<4;t1++)
{
for (int t2=0;t2<4-t1;t2++)
{
for (int t3=0;t3<4-t1-t2;t3++)
{
for (int t4=0;t4<4-t1-t2-t3;t4++)
{
if (t1*v1+t2*v2+t3*v3+t4==max)
{
flag=1;
goto CON;
}
}
}
}
}
CON:if (flag) continue;
return max-1;
}
}
int main()
{
int k1,k2,k3;//高1<k1<k2<k3,则km<2(k(m-1)+1)
int rtn=0,maxval=0;
int r1,r2,r3;
for (k1=2;k1<5;k1++)
{
for (k2=k1+1;k2<2*(k1+1);k2++)
{
for (k3=k2+1;k3<2*(k2+1);k3++)
{
rtn=max(k1,k2,k3);
if (maxval<rtn)
{
maxval=rtn;
r1=k1;r2=k2;r3=k3;
}
}
}
}
cout<<'\n'<<"The Result is:"<<r1<<'\t'<<r2<<'\t'<<r3;
cout<<'\n'<<"The Max Value is:"<<maxval<<'\n';
return 0;
}
HEROIN 2001-09-13
  • 打赏
  • 举报
回复
邮票可重复吗?
wjzhuang 2001-09-13
  • 打赏
  • 举报
回复
高程考试大纲有一个算法------背包问题.也有点关系
问题如下:
设有不同价值,不同重量的物品n件,求从n件物品中选取一部分物品的方案,使选中的物品总重量不超过指定的重量,但是价值之和为最大

使用递归算法解决
具体如下:
#include <stdio.h>
#define N 100
double linitW; //限制重量
double totV; //总价值
double maxv;
int option[N]; //选择情况
int cop[N]; //当前解
struct{
double weight;
double value;
}a[N];
int n; //物品种数

mytry(int i,double tw,double tv)
{

//考虑物品i包含在当前方案中的可能值
if(tw+a[i].weight<=limitW){ //包含物品i可以接受
cop[i]=1; //将物品i包含在当前方案中
if(i<n-1)
mytry(i+1,tw+a[i].weight,tv);
else{
//又一个完整方案,因为它比前面的方案好,以它作为最佳方案
for(k=0;k<n;k++) //当前方案为临时最佳方案保存
option[k] = cop[k];
maxv = tv;
}
cop[i] = 0; //恢复物品i不包含状态
}
//考虑物品i不包含在当前方案中的可能性
if(tv-a[i].value > maxv) //不包含物品i仅是可考虑的
if(i<n-1)
mytry(i+1,tv-a[i].value;
else{
//又一个完整方案,因为它比前面的方案好,以它作为最佳方案
for(k=0;k<n;k++) //当前方案作为临时最佳方案保存
option[k] = cop[k];
maxv = tv - a[i].value;
}
}
}
main()
{
int k;
double w,v;
printf("输入物品种数\n");
scanf("%d",&n);
printf("输入各物品的重量和价值\n");
for(totV=0.0,k=0;k<n;k++){
scanf("%1f%1f",&w,&v);
a[k].weight = w;
a[k].value = v;
totV += v;
}
printf("输入限制重量:\n");
scanf("%1f",&limitW);
maxv = 0.0;
for(k=0;k<n;k++)
cop[k] = 0;
mytry(0,0.0,totV);
for(k=0;k<n;k++)
if(option[k])
printf("%4d",k+1);
printf("\n总价值为 %2f\n",maxv);
}
jojopoper 2001-09-13
  • 打赏
  • 举报
回复
这个东西很有趣。。。到这个网站去式式:
go.163.com/ddsuanshu/shihsi.php
wjzhuang 2001-09-13
  • 打赏
  • 举报
回复
邮票问题

设有已知面额的邮票m种,每种有n张,用总数不超过n张的邮票,能从面额1开始,最多连续组成多少面额.(1<=m<=100,1<=n<=100,1<=邮票面额<=255) 输入:n m A[1..m](面额) 输出:MAX=(最大面额值) Input1:4 1 2 4 Output1:10 一看到这个题目,给人的第一感觉是用回溯算法,从面额1开始,每种面额都用回溯进行判断,算法复杂度并不高,但是当m,n取到极限值100时,程序明显超时,因此,回溯算法在这里并不可取. 能否用递推完成呢?我们有一个思路:从面额1开始,建立递推关系方程,就用范例来说吧,面额1,2,4只用1张邮票行了,面额3可以表示为面额1,2的邮票和1+1=2,面额5有两种表示方式MIN(面额1+面额4,面额2+面额3),照此类推,递推关系方程不难建立,由于1<=邮票面额<=255,1<=n<=100,因此MAX值最多可达到25500,25500次循环里必定还有嵌套循环,因此算法不加优化,很难在规定时间内得出最优值.这就需要递推的算法优化. 一味递推不寻求算法优化,速度较之搜索提高不少,但一旦数据规模过大,很难在规定时间内得出最优值.就拿邮票问题来说,以下是递推的一种方法:

{$A+,B-,D-,E+,F-,G-,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y-} {$M 16384,0,655360}
program stamps;
var f,fout:text; n,m,i,j,k:integer;
c:array [1..255] of integer; {面额}
a:array [1..31000] of integer; {递推数组}
bl:boolean;
procedure readfile; {读文件}
begin
assign(f,'STAMP.DAT');
reset(f); assign(fout,'STAMP.OUT');
rewrite(fout);
readln(f,n);
readln(f,m);
bl:=true;
for i:=1 to m do
begin
readln(f,c[i]);
if c[i]=1 then bl:=false;
end;
close(f);
end;
procedure work;
begin
if bl=true then write(fout,'MAX=0') {不存在面额1时输出无解}
else begin
i:=1; a[i]:=1;
repeat
i:=i+1;
for j:=1 to m do
if ((i mod c[j]=0) and ((i div c[j])<a[i]))
or (a[i]=0) {判断它能否被题目给定面额整除} then
a[i]:=i div c[j];
for j:=1 to trunc(i/2) do
if (a[j]+a[i-j]<a[i]) then a[i]:=a[j]+a[i-j]; {寻找(1<=j<=i),使A[j]+A[i-j]值最小}
until (a[i]>n) or (a[i]=0);
write(fout,'MAX=',i-1); {输出}
end;
close(fout);
end;
begin
readfile;
work;
end.

这种递推方法原理是:对于某种要求得到的面额,判断它能否被题目给定面额整除,再寻找(1<=j<=i),使A[j]+A[i-j]值最小,求出凑成某种面额最少邮票数,算法虽然简单,但还可以进一步优化.何不将用m种面额邮票作循环,建立递推关系式:A[i]=MAX(A[I-C[j]]+1),于是当取到极限值时,程序循环减少了约1.6*10^8次循环,递推优化作用不言而喻,下面是改进后的程序:

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+}
{$M 16384,0,655360}
program stamps_pro;
uses crt;
var
x:array [1..255] of byte;
pieces:array [0..30000] of byte;
max,m,n,i,j:integer;
filename:string;
f:text;
begin
{读文件}
assign(f,'STAMP.DAT'); reset(f);
readln(f,n); readln(f,m);
for i:=1 to m do readln(f,x[i]);
close(f);
fillchar(pieces,sizeof(pieces),0); max:=0;
{递推循环}
repeat
max:=max+1;
{循环,建立递推关系式PIECES[i]=MAX(PIECES[I-X[j]]+1)}
for i:=1 to m do if max-x[i]>=0 then
begin
if pieces[max]=0 then pieces[max]:=pieces[max-x[i]]+1;
if pieces[max]>pieces[max-x[i]]+1
then pieces[max]:=pieces[max-x[i]]+1;
end;
{输出无解}
if (pieces[max]=0) or (pieces[max]>n) then
begin
writeln('MAX=',max-1); exit;
end;
until false;
end.
程序优化后,运行四组测试数据时间如下: (测试机型:Pentium MMX 233)
测试数据 m N 未优化程序运行时间(秒) 优化程序运行时间(秒)
1 5 10 0.05 0.11
2 3 5 0.06 0.11
3 10 20 0.61 0.17
4 70 65 6.75 0.33
5 100 100 20.20 1.20

gloom 2001-09-13
  • 打赏
  • 举报
回复
1,4,6,15
最大到23
TR@SOE 2001-09-13
  • 打赏
  • 举报
回复
1,3,8,13,
最大到17。
柯本 2001-09-13
  • 打赏
  • 举报
回复
邮票可重复
gloom 2001-09-13
  • 打赏
  • 举报
回复
以前高考时用的好像是8421码,最大能 达到14

13,871

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧