波松分酒问题代码
参考文章:http://www.cnblogs.com/heaad/archive/2010/11/22/1884658.html
有一个12品脱的酒瓶,里面装满葡萄酒,另有8品脱和5品脱的瓶子各一个。问如何从中分出6品脱的酒出来?
分析:
假有有大中小三个酒瓶,容量分别为12、8、5。如何能分出6品脱的酒?
各个酒瓶中,初始酒量为{12,0,0},不管怎样倒,如果能倒成{6,6,0},那么这个问题就解决了。我们假设{12,0,0}是一个状态,{6,6,0}是一个状态。
倒酒的动作是有限的,可以大瓶倒入小瓶、小瓶也可以倒入大瓶,为了倒酒动作不重复,我们只选取三个动作:{"大瓶倒入中瓶","中瓶倒入小瓶","小瓶倒入大瓶"}。
现在的问题就是{12,0,0}经过N次动作变成{6,6,0},因此这就变成一个搜索问题。
下面用深度优先搜索方法编写,代码如下:
1 #include <stdio.h> 2 struct state 3 { 4 int L; //large 大瓶 5 int M; //medium 中瓶 6 int S; //small 小瓶 7 }; 8 9 struct state stt={12,0,0}; //酒瓶中的酒量 10 struct state s_record[20]; //记录每次动作后酒瓶中的酒量 11 12 struct state bottle={12,8,5};//酒瓶容量 13 14 char *action[]={"大瓶倒入中瓶","中瓶倒入小瓶","小瓶全部倒入大瓶"}; //三个动作 15 int a_record[20]; //记录每一次选择的动作 16 17 //三种动作0 1 2,此函数根据动作计算生成的状态, 18 //并判断此动作是否可以执行,如不能执行则返回0,执行成功则返回1 19 int rule(int i,int step) 20 { 21 struct state temp; 22 int j; 23 24 temp=stt; 25 26 if(i==0) //大瓶倒入中瓶(要么倒满中瓶,要么倒空大瓶,实际上总是能倒满中瓶) 27 { 28 if(stt.M==bottle.M)return 0; //如果中瓶本来是满的,则此动作不能执行 29 if(stt.L+stt.M<bottle.M)return 0; //如果大瓶与中瓶加起来不足中瓶的容量,则此动作不执行 30 temp.L=stt.L-(bottle.M-stt.M); //大瓶减去中瓶空的容量 31 temp.M=bottle.M; //中瓶倒满 32 } 33 if(i==1) //中瓶倒入小瓶(要么倒满小瓶,要么倒空中瓶) 34 { 35 if(stt.S==bottle.S)return 0; //如果小瓶是满的,不倒 36 if(stt.M==0)return 0; //如果中瓶是空的,不倒 37 if(stt.M+stt.S<bottle.S) //如果中瓶与小瓶加起来不足小瓶的容量,则倒空中瓶 38 { 39 temp.S=stt.M+stt.S; 40 temp.M=0; 41 } 42 else //否则倒满小瓶 43 { 44 temp.M=stt.M-(bottle.S-stt.S); 45 temp.S=bottle.S; 46 } 47 } 48 if(i==2) //小瓶全部倒入大瓶 49 { 50 //只有一种情况,当小瓶满了的时候才能倒入大瓶 51 if(stt.S<bottle.S)return 0; 52 53 temp.L=stt.L+stt.S; 54 temp.S=0; 55 } 56 for(j=0;j<step;j++) 57 if(s_record[j].L==temp.L&&s_record[j].M==temp.M&&s_record[j].S==temp.S) 58 return 0; 59 stt=temp; 60 return 1; 61 } 62 63 void fun(int step) 64 { 65 if(stt.M==6&&stt.L==6) 66 { 67 int i; 68 for(i=0;i<step;i++) 69 { 70 printf("%-20s\t%3d%3d%3d\n",action[a_record[i]],s_record[i].L,s_record[i].M,s_record[i].S); 71 } 72 printf("\n\n"); 73 } 74 else 75 { 76 int i; 77 for(i=0;i<3;i++) 78 { 79 if(rule(i,step)) 80 { 81 a_record[step]=i; //记录本次动作 82 s_record[step]=stt; //记录执行动作后的状态 83 fun(step+1); 84 } 85 } 86 } 87 } 88 int main() 89 { 90 fun(0); 91 return 0; 92 }
www.zandbin.com

浙公网安备 33010602011771号