关于Delphi版的大难题

dcyu 2002-08-17 03:54:02
原文:
求一递增整数序列,共36个数,第一个数为1,后面数逐渐增大
要求:任意两个整数的差(大整数减去小整数)均不相同
如:1 2 4 8 .....
求所有情况中第36个数(也就是最大数)最小时的解,即输出这36个数

算法不难,关键是,如何让程序算法效率高,也就是如何在有限的时间内算出结果
计算时间最好在3个小时内

本人认为本题可能没有精确的解,但我可以给出一个近似解,这个解如果有人发现有毛病的话提出来,给高分,如果谁能求出更精确解来,200分赠送。
1 2 5 11 22 36 54 76 100 129 162 200 244 292 343 402 465 534 607 679 745 806 863 913 958 997 1034 1064 1090 1113 1132 1148 1160 1168 1173 1175
本算法时间在1秒以内(Visual C++6.0)
如果没有回答出,只好up有分了。一周后结贴。
...全文
103 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
TempTask 2002-08-22
  • 打赏
  • 举报
回复
这是个很难的题:

假设a(n)是最优,在此基础上得到的a(n+1)
你无法证明是最优的。
所以不能类推,由a(n)->a(n+1);
所以每次得到a(n+1)时都必须将a(2),..,a(n)都全部推翻
穷举所有可能性才能保证a(n+1)是最优的,这个消耗的时间
是不可想象的。

除非在数学上论证a(n)最优则a(n+1)最优。
dcyu 2002-08-22
  • 打赏
  • 举报
回复
up
wshjobless 2002-08-21
  • 打赏
  • 举报
回复
昨天我作了一个程序,求最优解,
肯定是思路有问题,求8个数的序列用了二分钟
求36个数时,花了20个小时也没计算出来,只好停了
我还是等着看源码吧
dynamic_cast 2002-08-19
  • 打赏
  • 举报
回复
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;

var i,step,n:integer;
begin

step :=1;
n :=1;
for i := 1 to 36 do
begin
writeln(i,' ',n);
n := n+step;
step := step+1;
end;
readln;
end.
最后结果 631
Allen_cch 2002-08-19
  • 打赏
  • 举报
回复
to liuhf(liuhf) :
按照你的式子, x[n] - x[n-2] = x[n+1] - x[n] = x[n-1]
例如,你的数据 11 - 4 = 18 - 11 = 7
18 - 7 = 29 - 18 = 11
. . .........
wshjobless 2002-08-19
  • 打赏
  • 举报
回复
难道我的不是最优解
fangrk 2002-08-19
  • 打赏
  • 举报
回复
最优解很难找到。
我的方法只是贪婪法,我尝试过了,如果把第二个数字改为10,第36个是1923
wshjobless 2002-08-19
  • 打赏
  • 举报
回复
各位下面是我的程序,请指教!
本程序,本着以空间换时间的方法,可在1秒钟内解出
int icur_cha=1,int ia[36],icha[36],izu[1000];
ia[0]=1;
int main()
{
for(int ipos=1; ipos<36; ipos++)
{
while(izu[icur_cha]) icur_cha++;
ia[ipos] = ia[ipos-1]+icur_cha;
icha[ipos]=icur_cha;

int item_sum=0;
for (int i=ipos; i>0; i--)
{
itemp_sum+=icha[i];
izu[itemp]=1;
}
icur_cha++;
}
}
基本原理:
任意两个数之差就是两数之间所有相邻数差之和(数列由小到大)。
我用ia[]存放数列,用icha[]存放ia[]相邻两数之差,用izu[]的位置
表示已出现的各种差及所有连续差的和是否为真,用icur_cha表示当前
新产生的数与前一数之差,如果它在izu[]中出现,就++;
初步测试结果为:
1,2,4,8,13,21,31,45,61,76,97,119,.......
1010,1080,1157,1237,1318

liuhf 2002-08-19
  • 打赏
  • 举报
回复
我太随意了,把这个问题给看的太简单了,可以这样计算,
将数列分成两部分,用两个递增序列对应起来,如
1
1,2*
1,2*,4
1,2,5*,7
1,2,5*,10,12
1,2,5,11*,16,18
1,2,5,11*,19,24,26

有*的为连接点

前一半,X[n]=x[n-1]+x[n-2] +2
后一半,y[n]=y[n-1]+y[n-2] +1
然后,连接如下x[1],x[2],...x[n],y[n],y[n-1]...y[1]
不过,因为顺序相关,所以可以取得符合条件的解,但
不能保证是最优,尤其在数据大时,误差会更大。
fangrk 2002-08-19
  • 打赏
  • 举报
回复
我是用程序计算出来的:Dev-C++4(Win98SE)
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main()
{ vector<int> number(36);
set<int> distance1,distance2;
number[0]=1;
number[1]=2;
distance1.insert(number[1]-number[0]);
int i,k;
bool ok;
for(i=2;i<36;++i)
for(number[i]=number[i-1];;){
++number[i];
ok=true;
distance2.clear();
for(k=0;k<i;++k){
distance2.insert(number[i]-number[k]);
if(distance1.count(number[i]-number[k])){
ok=false;
break;
}
}
if(ok) {
distance1.insert(distance2.begin(),distance2.end());
break;
}
}
for(i=0;i<36;++i)
cout<<i+1<<":"<<number[i]<<endl;
return 0;
}
fangrk 2002-08-19
  • 打赏
  • 举报
回复
下面是我计算出来的
1:1
2:2
3:4
4:8
5:13
6:21
7:31
8:45
9:66
10:81
11:97
12:123
13:148
14:182
15:204
16:252
17:290
18:361
19:401
20:475
21:565
22:593
23:662
24:775
25:822
26:916
27:970
28:1016
29:1159
30:1312
31:1395
32:1523
33:1572
34:1821
35:1896
36:2029
ywqzxj 2002-08-19
  • 打赏
  • 举报
回复
关注中
  • 打赏
  • 举报
回复
假设n(i),n(j),n(k),n(l)为36个数的任意四个数。
那么任意两个相差不等就可以看作对i,j,k,l总是:
n(i) - n(j) != n(k)- n(l),也就是:
n(i) + n(l) != n(k) + n(j)
假设对于一个系列m已经满足上述关系那么只需要对n(m+1)这个数也满足关系就可以了。
设为n(m+1)为需找到的数。必须保证n(m+1) + n(i) != n(k) + n(l),
其中n(i),n(k),n(l)为系列m的任意数。
显然可以令n(m+1) = n(m)+n(m-1)+....n(1)+n(0)。
这样必然满足n(m+1) + n(i) != n(k) + n(l)。
我想用手工求这个系列也不会用一个小时吧!

  • 打赏
  • 举报
回复
千万别结贴!让大伙都想想嘛!
wshjobless 2002-08-19
  • 打赏
  • 举报
回复
我的方法只是一种解
确实不是最优解
现在能想到的办法,
除了用穷举
实在没有好方法
而我能用的方法
恐怕3个小时也解不出来
还是看各位的吧
eric_youbin 2002-08-19
  • 打赏
  • 举报
回复
大家为什么不换一个思路呢?
我算过,最小的数应该是 1+x0+x1+...+ x34 +36*35/2
你把x0...x34的规律找出来就知道是多少了!^_^

晚些时候在给你答案!
liuhf 2002-08-18
  • 打赏
  • 举报
回复
你给的数据肯定有问题,
如里面有2,22,1148,1168显然 1148-2 = 1168-22

我认为,可以取
1,4,7,11,18,29,47,....

除了你开始给定的1以外,后面
x[n] = x[n-1] + x[n-2]
我没验证过,不过,理论上应该成立,有问题告诉我。
dcyu 2002-08-18
  • 打赏
  • 举报
回复
做几个声明,希望有助大家理解题意。
1.随便的一组解谁都会找,问题就是在于能不能找到一组使第36个数最小的一组解2.还有631也是错的。不可能这630个不同的数刚好在一组数中间体现出来,在N=5的时候就已经体现出来了。
3.2000上的解不是最优的,是不是一个好的近似解不得而知,因为有人用穷举法论证了最优解<2000.
4.我的解也是错的,希望有人能够攻破难题。
个人认为本题是NP难问题。即便是求一个比穷举法在一定时间内得到答案还要优秀的近似解都很困难,如果有人能给出1800以内的算法,并且时间在1小时以内的话,就已经不错了。
wshjobless 2002-08-18
  • 打赏
  • 举报
回复
最好是这样
二进制
1
11
111
1111
11111



可惜36个1超出int范围
del_c_sharp 2002-08-17
  • 打赏
  • 举报
回复
http://www.csdn.net/expert/topic/934/934268.xml?temp=.1663019
加载更多回复(13)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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