我有一个程序问题,请高手指点!!!!!!

fossil2000 2001-06-02 01:45:00

四个人喝洒,但只有三个形状不规则的酒杯,两个是八两的形状不规则的酒怀,并装满了酒,一个是形状不规则的三两的空的酒怀,问怎么喝才能使四个人每人都喝到四两酒?写出程序或算法!?

请高手指点!我的EMAL是:fossilxiang@etang.com
...全文
143 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
fossil2000 2001-06-05
  • 打赏
  • 举报
回复
谢谢,此题可以结题了!谢谢。楼上的解法让我耳目一新!我正在写相应程序,有解后再来与大家分享!
fossil2000 2001-06-03
  • 打赏
  • 举报
回复
谢谢!谢谢所有的人,也谢谢MADE_IN_王子的精彩点评!对于此题的程序我正在以你的答案为基础想呢!
starfish 2001-06-03
  • 打赏
  • 举报
回复
TO: Speedeer(急速人),
我说的是[量水问题],问题如下:
有三个分别装有a升水,b升水,c升水的量筒,其中a,b互质,c>b>a>0,现在c筒装满水,问能否在c筒中量出d升水(c>d>0)。若可以,给出方案。
当时感觉顶楼的提出的问题和量水问题有点相似,所以随口说了一下。现在看看好像不太一样。
所谓模数方程,就是模线性方程,即形如 ax ≡ b (mod c) 形式的方程,其中a,b,c是常数,x是自变量,这个方程表示ax mod c = b mod c,即ax和b模c同余。
关于那个量水问题,用模数方程解比较方便,具体算法分析如下。

量水过程实际上就是倒来倒去,每次倒的时候总有如下几个特点:
1。总有一个筒中的水没有变动;
2。不是一个筒被倒满酒是另一个筒被倒光;
3。c筒仅起到中转作用,而本身的容积除了必须足够装下a筒和b筒全部的水以外,别无其他的限制;
这样,假设整个倒水过程中对a筒倒满了x次,对b筒倒满了y次,则:
ax + by = d, (1)
上式的x,y为整数,而且既可以是正整数(表示该筒(a或b)被c筒的水倒满的次数),也可以是负整数(表示该筒(a或b)被倒满后又倒回到c筒的次数)。
一般可以用穷举法来解方程(1),但是这种方法局限性很大。我们可以将方程转化为:
ax = -by + d,
进一步变为
ax ≡ d (mod b), (20
这样问题就变成了求解模数方程(2)的解的问题。解x的个数就是可行方案的总数。其中xi表示第i种方案中a筒倒满的次数,xi代入方程(1)后求出来的yi表示b筒倒满的次数。

例如:有三个量筒,a=3,b=7,c=10,求c筒中量出5升水的所有方案。
解方程 : 3x ≡ 5 (mod 7) 得到 x1 = 4, y1=-1 和x2=-3, y2=2,
这两个解对应的倒水方案如下:

方案一: x1=4, y1=-1

次数 a b c 说明
1 0 0 10 初始状态
2 3 0 7 从c倒水到a中,把a倒满
3 0 3 7 从a倒水到b中,把a倒空
4 3 3 4 从c倒水到a中,把a倒满
5 0 6 4 从a倒水到b中,把a倒空
6 3 6 1 从c倒水到a中,把a倒满
7 2 7 1 从a倒水到b中,把b倒满
8 2 0 8 从b倒水到c中,把b倒空
9 0 2 8 从a倒水到b中,把a倒空
10 3 2 5 从c倒水到a中,把a倒满
11 0 5 5 从a倒水到b中,把a倒空

整个过程中,一共有4次“从c倒水到a中,把a倒满”,有1次“从b倒水到c中,把b倒空”;


方案二: x2=-3, y2=2

次数 a b c 说明
1 0 0 10 初始状态
2 0 7 3 从c倒水到b中,把b倒满
3 3 4 3 从b倒水到a中,把a倒满
4 0 4 6 从a倒水到c中,把a倒空
5 3 1 6 从b倒水到a中,把a倒满
6 0 1 9 从a倒水到c中,把a倒空
7 1 0 9 从b倒水到a中,把b倒空
8 1 7 2 从c倒水到b中,把b倒满
9 3 5 2 从b倒水到a中,把a倒满
10 0 5 5 从a倒水到c中,把a倒空

整个过程中,一共有3次“从a倒水到c中,把a倒空”,有2次“从c倒水到b中,把b倒满”;

至于其中解模数方程的方法,一些关于数论的书上有介绍,说起来也比较麻烦,有很多的定理公式,我直接给出一个程序吧:


/********************************************

求解模线性方程 ax=b (mod n) ,n>0
copyright starfish
2000/10/24

*********************************************/

void modular_linear_equation_solver(int a, int b, int n)
{
int e,i,d;
int x,y;
d = ext_euclid(a, n, x, y);
if (b%d>0) {
printf("No answer!\n");
} else {
e=(x*(b/d))%n;
for (i=0; i<d; i++) //notice! Here x maybe less than zero!
printf("The %dth answer is : %ld\n",i+1,(e+i*(n/d))%n);
}
}


其中用到的ext_euclid 函数如下:

/*********************************************

扩展欧几里德算法求gcd(a,b)=ax+by

copyright starfish
2000/10/24

*********************************************/

int ext_euclid(int a,int b,int &x,int &y)
{
int t,d;
if (b==0) {x=1;y=0;return a;}
d=ext_euclid(b,a %b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}

不知道这样解答是否满意,我打字可是打得累死了:)
Speedeer 2001-06-02
  • 打赏
  • 举报
回复
能不能来点源程序?
Speedeer 2001-06-02
  • 打赏
  • 举报
回复
模数方程?是什么东东?
starfish 2001-06-02
  • 打赏
  • 举报
回复
者和那个称油问题差不多吧,好像可以用模数方程解决,还没有细想。
bieli 2001-06-02
  • 打赏
  • 举报
回复
楼上的确实比较清楚,我的也正是这个意思,不过我没学过算法,表达不好!
嘿嘿……
made_in_ 2001-06-02
  • 打赏
  • 举报
回复
8 8 0
5 8 3
5 8 0//A喝3两
2 8 3
0 8 3//B喝2两
3 8 0
3 5 3
6 5 0
6 2 3
8 2 1
8 2 0//A喝一两,已经满4两
8 0 2
7 0 3
7 3 0
4 3 3
4 6 0
1 6 3
1 8 1
0 8 1//C喝一两
0 8 0//D喝一两
0 5 3
0 5 0//C喝三两,已经满4两
0 2 3
0 2 0//D喝三两,已经满4两
0 0 0//B喝二两,已经满4两。完毕。
made_in_ 2001-06-02
  • 打赏
  • 举报
回复
这下比较清楚了吧?呵呵
liuto 2001-06-02
  • 打赏
  • 举报
回复
to ksxy & made_in
噢,没看清楚,呵呵,不好意思:)
bieli 2001-06-02
  • 打赏
  • 举报
回复
还有—希望给点分……
bieli 2001-06-02
  • 打赏
  • 举报
回复
我认为是这样的:
假设为A、B、C、D四人;首先由A喝3两,然后B喝2两。这很容易实现。
还剩下11两,刚好装在一个8两的杯,一个3两的杯,可利用另一个8两杯,向其中倒3次用3两杯装的酒。最后3两杯中剩下的就是1两酒。给A喝。这时A已喝4两,接下来利用同样的方法分别倒出两个1两给C、D喝。然后,再给C、D分别喝3两。最后将剩下的酒给B喝就OK了!

小弟不才,表达不好,希望大家能看明白。
made_in_ 2001-06-02
  • 打赏
  • 举报
回复
to 楼上的
题目说的是两个8两杯都是满的,而你的步骤中却用到了个空8两杯
liuto 2001-06-02
  • 打赏
  • 举报
回复
怎么不能?
8 8 3
1 8 0 0
2 5 0 3
3 5 3 0
4 2 3 3
5 0(drink) 6 0
6 0 8(add) 0
7 0 5 3
8 3 5 0
9 3 2 3
10 6 2 0
11 6 0(drink) 0
......
ksxy 2001-06-02
  • 打赏
  • 举报
回复
老大啊,8-3-3可以实现么?他只有3个杯子:)

还是回溯吧~
liuto 2001-06-02
  • 打赏
  • 举报
回复
每次喝2两呀
8-3-3 = 2, 把那两个3两倒到另一个8两杯,下次添满再来。

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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