求一个算法的程序?

daydayup234 2007-01-20 11:24:08
等宽等高的长方体水箱,长度不等,各个水箱长度已知。在长度方向水箱首尾相接,水箱编序1、2、3、……k、k+1,在水箱相接的隔板底部安有单向水阀。初始状况,水箱分别盛不一定等高的水,各高度已知,高度均低于水箱高度。打开所有水阀,水箱k+1中的水可能会流进水箱k,遵循连通器原则;但是,水箱k中的水不会流进水箱k+1,因为水阀单向。稳定状态后,求知各个水箱中水的高度?
...全文
1525 53 打赏 收藏 转发到动态 举报
写回复
用AI写文章
53 条回复
切换为时间正序
请发表友善的回复…
发表回复
daydayup234 2007-01-24
  • 打赏
  • 举报
回复
看来
我真是丢密码了
daydayup234 2007-01-24
  • 打赏
  • 举报
回复
Tmain_ *main_;
//---------------------------------------------------------------------------
__fastcall Tmain_::Tmain_(TComponent* Owner):TForm(Owner)
{
Caption="单向水阀水箱问题";
Memo1->Lines->Clear();
Memo1->ScrollBars=ssVertical;
}
//---------------------------------------------------------------------------
void Tmain_::calc1(const double *srcLong,const double *srcHieght,double *Result,int count)
{
int i;
bool stopped;
double temp,d1,d2,d3,d4;

for(i=0;i<count;i++)(*(Result+i))=(*(srcHieght+i))*(*(srcLong+i));

while(true)
{
Application->ProcessMessages();
stopped=true;
for(i=1;i<count;i++)
{
d1=*(Result+i);
d2=*(srcLong+i);
d3=*(Result+i-1);
d4=*(srcLong+i-1);
if((d1/d2-d3/d4)>0.000001)
{
temp=(d1+d3)/(d2+d4);
(*(Result+i))=temp*d2;
(*(Result+i-1))=temp*d4;
stopped=false;
}
}

if(stopped)
{
for(i=0;i<count;i++) (*(Result+i))=(*(Result+i))/(*(srcLong+i));
return;
}
}
}
//---------------------------------------------------------------------------
void __fastcall Tmain_::N1Click(TObject *Sender)
{
const int MYMAXLONG=80;
double _srcLong[MYMAXLONG], _srcHieght[MYMAXLONG],_Result[MYMAXLONG];
int i;
Randomize();
for(i=0;i<MYMAXLONG-1;i++)
{
_srcLong[i]=RandomRange(10,2000); //#include <Math.hpp>
_srcHieght[i]=RandomRange(100,2000); //random
}

Memo1->Lines->Clear();
calc1(_srcLong, _srcHieght,_Result,MYMAXLONG);
Memo1->Lines->Add("高度______长度");
for(i=0;i<MYMAXLONG-1;i++) Memo1->Lines->Add(FormatFloat("0.0###",_srcHieght[i])+" ______"+ FormatFloat("0.0###",_srcLong[i]));
Memo1->Lines->Add("\r\n结果______________________________________");
Memo1->Lines->Add("高度______长度");
for(i=0;i<MYMAXLONG-1;i++) Memo1->Lines->Add(FormatFloat("0.0###", RoundTo(_Result[i],-4))+" ______"+ FormatFloat("0.0###",_srcLong[i]));
}
//----------------------------------
constantine 2007-01-23
  • 打赏
  • 举报
回复
提醒一下,一定不要改为>,一定要用精度判断,不然这个优化代码就铁定会出问题,这个跟我用double有关系吧
constantine 2007-01-23
  • 打赏
  • 举报
回复
这个是我给你贴的部分,影响比较小,不用考虑
RESULT:
1602.7568
1602.7569
1602.7570
1602.7570
1602.7571
1602.7571
1602.7572
1602.7573
1602.7573
1602.7573
1602.7574
1098.0000
1079.1954
1079.1954
1079.1954
1079.1955
1061.9812
1061.9812
588.5061
588.5062
588.5063
588.5063
588.5064
588.5064
210.0000
constantine 2007-01-23
  • 打赏
  • 举报
回复
Height -- Length:
224 -- 271
1577 -- 1982
1302 -- 297
1520 -- 1966
401 -- 466
1924 -- 1576
1576 -- 1669
1328 -- 581
1881 -- 1813
1487 -- 60
1843 -- 1820
1098 -- 1900
330 -- 1988
264 -- 213
1451 -- 876
1775 -- 1922
805 -- 1403
1468 -- 888
563 -- 1496
265 -- 1549
754 -- 844
732 -- 1512
1982 -- 102
787 -- 204
210 -- 1214
RESULT:
1602.7638
1602.7614
1602.7609
1602.7599
1602.7597
1602.7576
1602.7567
1602.7556
1602.7551
1602.7500
1602.7500
1098.0000
1079.1972
1079.1972
1079.1952
1079.1935
1061.9815
1061.9809
588.5080
588.5068
588.5059
588.5053
588.5000
588.5000
210.0000
constantine 2007-01-23
  • 打赏
  • 举报
回复
//这个是简单优化过的,开始我写的以为顺序有关系,慢太多了
procedure calc1(const srcLong, srcHieght: array of Double; var Result: array of Double);
var
i, k: Integer;
l, h: Integer;
flag: Boolean;
temp:Double;
begin
l := Low(srcLong);
h := High(srclong);
//获得有效体积(比例),宽,高一样,不用考虑
for i := h downto l do
begin
Result[i] := srcHieght[i] * srcLong[i];
end;

while True do
begin
Application.ProcessMessages;
flag := True;
for i := h downto l + 1 do
begin
//if ((Result[i] / srcLong[i]) > (Result[i - 1] / srclong[i - 1])) then
if ((Result[i] / srcLong[i]) - (Result[i - 1] / srclong[i - 1]) > 0.0001) then
begin
temp:= (result[i]+ result[i-1])/ (srcLong[i]+srcLong[i-1]);
result[i] := temp*srcLong[i];
result[i - 1] := temp*srcLong[i-1];
flag := False;
end;
end;

//满足结算出实际高度
if flag then
begin
for k := h downto l do
begin
Result[k] := Result[k] / srcLong[k];
end;
Exit;
end;
end;
end;


procedure TForm1.Button1Click(Sender: TObject);
const MAXLONG=25;
var
_srcLong, _srcHieght: array of Double;
_Result: array of Double;
i:Integer;
begin
SetLength(_srcLong, MAXLONG);
SetLength(_srcHieght, MAXLONG);
SetLength(_Result, MAXLONG);
Randomize;
for i := 0 to MAXLONG-1 do
begin
_srcLong[i]:=RandomRange(10,2000);
_srcHieght[i]:=RandomRange(100,2000);
end;

Memo2.Lines.Clear;

calc1(_srcLong, _srcHieght, _Result);
Memo2.Lines.Add('Height -- Length:');
for i := 0 to MAXLONG-1 do
begin
Memo2.Lines.Add(FormatFloat('0.#',_srcHieght[i])+ ' -- ' + FormatFloat('0.#',_srcLong[i]));
end;
Memo2.Lines.Add('RESULT:') ;
for i := 0 to MAXLONG-1 do
begin
Memo2.Lines.Add(FormatFloat('0.0###', RoundTo(_Result[i],-4)));
end;
end;
daydayup234 2007-01-23
  • 打赏
  • 举报
回复
delphi可以阿,谢谢

lz怎么会不会写?————估计偶IQ卡密码丢了,^-^
constantine 2007-01-23
  • 打赏
  • 举报
回复
既然顺序不用考虑,lz怎么会不会写?
看得懂delphi我就给你贴,不然算了,我现在都不用bcb写代码了。环境不允许。
constantine 2007-01-23
  • 打赏
  • 举报
回复
我错了,回头仔细想了一下,顺序确实不怎么影响结果,影响的效果小的很小,一时想歪了。
测试出来影响结果只达到0.01级别。
汗~~
daydayup234 2007-01-23
  • 打赏
  • 举报
回复
2天没上来。
首先感谢各位热忱回答,特别安吉尔,keiy() 社区专家。

1)敞口
2)不是工程上的应用,但是这个确实是应用实际的问题。
3)关于“先后开”,我粗想,这个与“最终平衡”后
没关系,可能与过程有关。非得限定开启顺序,就限定为这样如何:

1、2之间先开,直到它们平衡。然后开2、3之间,直到1、2、3平衡。
依次类推......直到最后 。

4)安吉尔说的,“这样的问题一般都不能考虑水的高度真的相等,要允许一个误差.
所以一般不是直接比较,而是相减然后判断差值是否在某个比较小的范围内,比如0.0001,这样
另外为了简单,动态数组最好用double,不要用int.”,这个确实,我注意到了。
说到“微积分”, 可能我问题不合适,误导思路了,这不是一个物理题。
5)wingao、renzaijiang代码我还没细看,我慢慢看。但是我再提醒下,难度在于以下现象:假如高度比较

起初2>1→ 1、2加权平均→3< 1、2,不动→4>3→ 3、4加权平均,这个时候,(1、2)可能<(3、4),也可能相等等,这时候
比较区间长度变化了,请大家注意,麻烦在此......

6)容器?链表?我搞不定了,还是请高手费心给个代码解答,
7)我认可abseabse意见,不过代码写正确不好对付,也请keiy()继续关注。
daydayup234 2007-01-23
  • 打赏
  • 举报
回复
我先看了constantine的代码,谢谢帮忙
1)特别规范的代码习惯,该用const的地方,学习你
2)delphi不太熟, l := Low(srcLong); h := High(srclong);
是srclong数组的下标最小最大么?
3)可是,代码好像就是紧邻2个水箱判断与平衡注流,但是 紧邻2个水箱 的这种平衡注流
不是 一遍过手。因为,水阀一旦打开就都不关了。
例如:只有a,b,c,d四水箱,a,b平衡注流完成;b,c再平衡注流,有可能a,b要从新再 平衡注流。同样随后的c,d平衡注流,也可能要求前面做过的平衡注流还得做。至少是判断是必须的。

可能会说,从后往前平衡注流呢,细想想还是会影响做过的平衡注流,可能重做。

可能我对constantine的代码理解不全,请赐教
wingao 2007-01-22
  • 打赏
  • 举报
回复
因为水阀单向,水箱k+1中的水可能会流进水箱k,,水箱k中的水不会流进水箱k+1。所以应该就是简单的判断水箱k+1的水位有没有水箱k的高。而且最终稳定态唯一,与如何开水阀应该没关系。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int number;
struct box
{
int lastdiff;
float waterlevel;
int flag;
};
struct box *box;
float average;
int i,j,k;
printf("input the nember of box\n");
scanf("%d",&number);
box=malloc(number*sizeof(struct box));
for(i=0;i<number;i++)
{
printf("\ninput the water level of box\nbox[%d]=",i);
scanf("%f",&(box[i].waterlevel));
box[i].lastdiff=i;
if(i==0)
box[i].flag=0;
else
box[i].flag=1;
}
for(i=1;i<number;i++)
{
k=i;
while(box[k-1].waterlevel<box[k].waterlevel)
{
if(!box[k].flag)
break;
average=((k-box[k-1].lastdiff)*box[k-1].waterlevel+(i-k+1)*box[i].waterlevel)/(i-box[k-1].lastdiff+1);
for(j=box[k-1].lastdiff;j<=i;j++)
{
box[j].waterlevel=average;
box[j].lastdiff=box[k-1].lastdiff;
}
k=box[i].lastdiff;
}
}
for(i=0;i<number;i++)
printf("\nbox[%d]=%f\n",i,box[i].waterlevel);
system("pause");
}
xk2y 2007-01-22
  • 打赏
  • 举报
回复
强啊啊啊啊```
renzaijiang 2007-01-22
  • 打赏
  • 举报
回复
struct box
{
int num;
int h;
} arr[n];
定义队列 queue();
for(int i=0;i<n;i++)
{

if(arr[i].h<arr[i+1].h) continue;
else enqueue(i);
}
int k=0;
while(!queue.empty())
{
sum=0;
for(int i=k;i<=queue.front();i++)
sum+=arr[i].h;
for(int i=k;i<=queue.front();i++)
arr[i].h=sum/(queue.front()-k+1);
dequeue();
k=i;
}







wlp555ren 2007-01-22
  • 打赏
  • 举报
回复
题目都没有看懂。。关注。。。
meiwiles 2007-01-22
  • 打赏
  • 举报
回复
滿世界都是金子!
xtyceiiiu 2007-01-22
  • 打赏
  • 举报
回复
abseabse() 和
huanyun(无妻徒刑)
思维敏捷,一语道破天机.

huanyun 2007-01-22
  • 打赏
  • 举报
回复
不太好表达
其实就是递归 将升序平均 直到没有升序就可以了
huanyun 2007-01-22
  • 打赏
  • 举报
回复
一个算法

a = 0

从a到K+1 找一个升序 到n时得到 n > n - 1 对a-n做平均

a = n
从a到K+1 找一个升序 到n时得到 n > n - 1 对a-n做平均

如果 n == k+1 令 a = 0 直到 从a到K+1无法找到升序
xtyceiiiu 2007-01-22
  • 打赏
  • 举报
回复
不管什么情况,水的流向都是左向右的方向,所以情况并不复杂.左边的水位最永远不会高于右边的水位.
加载更多回复(33)

13,825

社区成员

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

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