农夫过河

一个农夫在河边带了一只狼、一只羊和一颗白菜,他需要把这三样东西用船带到河的对岸。然而,这艘船只能容下农夫本人和另外一样东西。如果农夫不在场的话,狼会吃掉羊,羊也会吃掉白菜。请编程为农夫解决这个过河问题。

问题分析

根据问题描述可知,该问题涉及的对象较多,而且运算步骤也较为复杂,因此,在使用C语言实现时,首先需要将具体问题数字化。

由于整个过程的实现需要多步,而不同步骤中各个事物所处的位置不同,因此可以定义一个二维数组或者结构体来表不四个对象狼(wolf)、羊(goat)、白菜(cabbage)和农夫(farmer)。对于东岸和西岸,可以用east和west表示,也可以用0和1来表示, 以保证在程序设计中的简便性。

题目要求给出四种事物的过河步骤,没有对先后顺序进行约束,这就需要给各个事物依次进行编号,然后依次试探,若试探成功,再进行下一步试探。因此,解决该问题可以使用循环或者递归算法,以避免随机盲目运算而且保证每种情况都可以试探到。

题目要求求出农夫带一只羊,一条狼和一颗白菜过河的所有办法,所以依次成功返回运算结果后,需要继续运算,直至求出所有结果,即给出农夫不同的过河方案。

算法设计

本程序使用递归算法,定义二维数组int a[N][4]存储每一步中各个事物所处的位置。二维数组的一维下标表示当前进行的步骤,第二维下标可能的取值为0〜3,在这里规定它与四种事物的具体对应关系为:0——狼、1——羊、2——白菜、3——农夫。接着再将东岸和西岸数字化,用0表示东岸,1表示西岸,该信息存储在二维数组的对应元素中。

定义Step变量表示渡河的步骤,则成功渡河之后,a数组中的存储状态为:
a[Step][0]   1
a[Step][1]   1
a[Step][2]   1
a[Step][3]   1

因为成功渡河后,狼、羊、白菜和农夫都在河的西岸,因此有:

a[Step][0]+a[Step][1]+a[Step][2]+a[Step][3]=4

题目中要求狼和羊、羊和白菜不能在一起,因此若有下述情况出现:

a[Step][1]!=a[Step][3] && (a[Step][2]==a[Step][1] || a[Step][0]=a[Step][1])

则发生错误,应返回操作。

在程序实现时,除了定义a数组来存储每一步中各个对象所处的位置以外,再定义一维数组b[N]来存储每一步中农夫是如何过河的。

程序中实现递归操作部分的核心代码为:

     
     
  1. for(i=-1; i<=2; i++)
  2. {
  3. b[Step]=i;
  4. memcpy(a[Step+1], a[Step], 16); /*复制上一步状态,进行下一步移动*/
  5. a[Step+1][3]=1-a[Step+1][3]; /*农夫过去或者回来*/
  6. if(i == -1)
  7. {
  8. search(Step+1); /*进行第一步*/
  9. }
  10. else
  11. if(a[Step][i] == a[Step][3]) /*若该物与农夫同岸,带回*/
  12. {
  13. a[Step+1][i]=a[Step+1][3]; /*带回该物*/
  14. search(Step+1); /*进行下一步*/
  15. }
  16. }
每次循环从-1到2依次代表农夫渡河时为一人、带狼、带羊、带白菜通过,利用语句“b[Step] = i”分别记录每一步中农夫的渡河方式,语句“a[Step+1][i] = a[Step+1][3]”是利用赋值方式使该对象与农夫一同到对岸或者回到本岸。若渡河成功,则依次输出渡河方式。“i<=2”为递归操作的界限,若i=2时仍无符合条件的方式,则渡河失败。

上面代码表示若当前步骤能使各值均为1,则渡河成功,输出结果,进入回归步骤。若当前步骤与以前的步骤相同,则返回操作,代码如下:

     
     
  1. if(memcmp(a[i],a[Step],16) == 0)
  2. {
  3. return 0;
  4. }
若羊和农夫不在一块而狼和羊或者羊和白菜在一块,则返回操作,判断代码如下:

     
     
  1. if(a[Step][1]!=a[Step][3] && (a[Step][2] == a[Step][1] || a[Step][0] == a[Step][1]))
  2. {
  3. return 0;
  4. }
下面是完整的代码:

     
     
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #define N 15
  5. int a[N][4];
  6. int b[N];
  7. char *name[]=
  8. {
  9. " ",
  10. "and wolf",
  11. "and goat",
  12. "and cabbage"
  13. };
  14. int search(int Step)
  15. {
  16. int i;
  17. /*若该种步骤能使各值均为1,则输出结果,进入回归步骤*/
  18. if(a[Step][0]+a[Step][1]+a[Step][2]+a[Step][3] == 4)
  19. {
  20. for(i=0; i<=Step; i++) /*能够依次输出不同的方案*/
  21. {
  22. printf("east: ");
  23. if(a[i][0] == 0)
  24. printf("wolf ");
  25. if(a[i][1] == 0)
  26. printf("goat ");
  27. if(a[i][2] == 0)
  28. printf("cabbage ");
  29. if(a[i][3] == 0)
  30. printf("farmer ");
  31. if(a[i][0] && a[i][1] && a[i][2] && a[i][3])
  32. printf("none");
  33. printf(" ");
  34. printf("west: ");
  35. if(a[i][0] == 1)
  36. printf("wolf ");
  37. if(a[i][1] == 1)
  38. printf("goat ");
  39. if(a[i][2] == 1)
  40. printf("cabbage ");
  41. if(a[i][3] == 1)
  42. printf("farmer ");
  43. if(!(a[i][0] || a[i][1] || a[i][2] || a[i][3]))
  44. printf("none");
  45. printf("\n\n\n");
  46. if(i<Step)
  47. printf(" the %d time\n",i+1);
  48. if(i>0 && i<Step)
  49. {
  50. if(a[i][3] == 0) /*农夫在本岸*/
  51. {
  52. printf(" -----> farmer ");
  53. printf("%s\n", name[b[i] + 1]);
  54. }
  55. else /*农夫在对岸*/
  56. {
  57. printf(" <----- farmer ");
  58. printf("%s\n", name[b[i] + 1]);
  59. }
  60. }
  61. }
  62. printf("\n\n\n\n");
  63. return 0;
  64. }
  65. for(i=0; i<Step; i++)
  66. {
  67. if(memcmp(a[i],a[Step],16) == 0) /*若该步与以前步骤相同,取消操作*/
  68. {
  69. return 0;
  70. }
  71. }
  72. /*若羊和农夫不在一块而狼和羊或者羊和白菜在一块,则取消操作*/
  73. if(a[Step][1]!=a[Step][3] && (a[Step][2] == a[Step][1] || a[Step][0] == a[Step][1]))
  74. {
  75. return 0;
  76. }
  77. /*递归,从带第一种动物开始依次向下循环,同时限定递归的界限*/
  78. for(i=-1; i<=2; i++)
  79. {
  80. b[Step]=i;
  81. memcpy(a[Step+1], a[Step], 16); /*复制上一步状态,进行下一步移动*/
  82. a[Step+1][3]=1-a[Step+1][3]; /*农夫过去或者回来*/
  83. if(i == -1)
  84. {
  85. search(Step+1); /*进行第一步*/
  86. }
  87. else
  88. if(a[Step][i] == a[Step][3]) /*若该物与农夫同岸,带回*/
  89. {
  90. a[Step+1][i]=a[Step+1][3]; /*带回该物*/
  91. search(Step+1); /*进行下一步*/
  92. }
  93. }
  94. return 0;
  95. }
  96. int main()
  97. {
  98. printf("\n\n 农夫过河问题,解决方案如下:\n\n\n");
  99. search(0);
  100. return 0;
  101. }
运行结果:
             农夫过河问题,解决方案如下:


east: wolf  goat  cabbage  farmer               west: none


                       the 1 time
east: wolf  cabbage               west: goat  farmer 


                       the 2 time
                  <-----  farmer        
east: wolf  cabbage  farmer               west: goat 


                       the 3 time
                  ----->  farmer and wolf
east: cabbage               west: wolf  goat  farmer 


                       the 4 time
                  <-----  farmer and goat
east: goat  cabbage  farmer               west: wolf 


                       the 5 time
                  ----->  farmer and cabbage
east: goat               west: wolf  cabbage  farmer 


                       the 6 time
                  <-----  farmer        
east: goat  farmer               west: wolf  cabbage 


                       the 7 time
                  ----->  farmer and goat
east: none             west: wolf  goat  cabbage  farmer 






east: wolf  goat  cabbage  farmer               west: none


                       the 1 time
east: wolf  cabbage               west: goat  farmer 


                       the 2 time
                  <-----  farmer        
east: wolf  cabbage  farmer               west: goat 


                       the 3 time
                  ----->  farmer and cabbage
east: wolf               west: goat  cabbage  farmer 


                       the 4 time
                  <-----  farmer and goat
east: wolf  goat  farmer               west: cabbage 


                       the 5 time
                  ----->  farmer and wolf
east: goat               west: wolf  cabbage  farmer 


                       the 6 time
                  <-----  farmer        
east: goat  farmer               west: wolf  cabbage 


                       the 7 time
                  ----->  farmer and goat
east: none             west: wolf  goat  cabbage  farmer 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要解决这个农夫过河的问题,可以使用递归算法。首先,我们需要定义一个二维数组来表示每一步中各个物品所处的位置。其中,0表示狼,1表示羊,2表示白菜,3表示农夫。另外,我们还需要定义两个一维数组来表示东岸和西岸的状态。 初始情况下,农夫、狼、羊和白菜都在西岸。我们可以将这个状态保存在数组w中,其中w=1表示狼在西岸,w=2表示羊在西岸,w=3表示白菜在西岸。同时,我们将东岸的状态保存在数组e中,初始状态下都为0。 接下来,我们可以使用递归函数来解决这个问题。在每一步中,我们都需要判断当前状态是否满足条件,即羊和农夫是否在一起而狼和羊或羊和白菜在一起。如果满足条件,则继续进行下一步试探;否则,返回上一步。 在试探下一步时,我们可以遍历所有可能的物品组合,农夫可以选择带一样物品过河或者不带物品过河。如果选择带物品过河,就需要更新数组w和e的状态;如果选择不带物品过河,就直接进入下一步的递归。 通过不断地试探和递归,直到找到所有的过河方案。每一次成功返回结果后,都需要继续运算,直至求出所有结果。 代码示例: ```python def cross_river(w, e, li, cnt): if w == [0, 0, 0]: print(li) return for i in range(3): if w[i] == cnt: new_w = w.copy() new_e = e.copy() new_w[i] = 0 new_e[i] = cnt if (new_w[1] != new_w[2] or new_w[1] == 0) and (new_w[0] != new_w[1] or new_w[0] == 0): li.append(i) cross_river(new_w, new_e, li, cnt + 1) li.pop() w = [1, 2, 3] # 西岸初始状态,0代表没有,1代表白菜,2代表羊,3代表狼 e = [0] * 3 # 东岸初始状态 li = [] # 储存每一次所带的东西 cnt = 0 # 记录农夫所在位置,单数代表西岸,双数代表东岸 cross_river(w, e, li, cnt) ``` 这样,就可以求出农夫过河的所有方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值