- 题目连接:
- http://poj.org/problem?id=3414
- http://bailian.openjudge.cn/practice/3151/
- 总时间限制: 1000ms 内存限制: 65536kB
- 描述
-
You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:
- FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap;
- DROP(i) empty the pot i to the drain;
- POUR(i,j) pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).
Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.
- 输入
-
On the first and only line are the numbers A, B, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).
- 输出
-
The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.
- 样例输入
-
3 5 4
- 样例输出
-
6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1)
题目大意与题解:http://blog.csdn.net/freedomcheng/article/details/7385666
给出两个杯子容积,初始都为空杯子,给出目标水量,可以执行一些操作,分别是倒空一个杯子,倒满一个杯子,和将一个杯子的水倒到另一个中,问得到目标水量要进行至少多少次以及每次都是什么
FILL(1)表示倒满1杯子,POUR(2,1)表示将2杯子里的水倒进1杯子中,DROP(1)表示倒空1杯子。
本体为广度优先生成树,每次对六种操作进行广度搜索,用二维数组进行状态是否出现过的标记,并记录每次出现的节点的父节点,最后用递归进行输出。
POJ的题判与百炼的题判稍微不一样,下面是POJ的代码。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 int a,b,c; 7 8 9 struct node 10 { 11 int aa;//a杯子里的水量 12 int bb;//b杯子里的水量 13 int parent;//父节点编号 14 int ope;//执行什么操作得到该节点 15 int level;//层次 16 node(int x,int y,int p,int o,int l):aa(x),bb(y),parent(p),ope(o),level(l){}//构造函数,为了方便返回该结构体变量 17 node(){}//有自定义构造函数的时候必须有一个默认构造函数 18 }; 19 20 21 node nod[1000000]; 22 bool fl[205][205]; 23 int stk[1000000]; 24 25 26 void output(int p) 27 { 28 int top=0; 29 stk[0]=p;//数组模拟栈实现递归 30 while(nod[stk[top]].parent!=-1) 31 { 32 top++; 33 stk[top]=nod[stk[top-1]].parent; 34 } 35 for(int i=top;i>=0;i--) 36 { 37 switch(nod[stk[i]].ope) 38 { 39 case 0: 40 { 41 printf("DROP(1) "); 42 } 43 break; 44 case 1: 45 { 46 printf("FILL(1) "); 47 } 48 break; 49 case 2: 50 { 51 printf("DROP(2) "); 52 } 53 break; 54 case 3: 55 { 56 printf("FILL(2) "); 57 } 58 break; 59 case 4: 60 { 61 printf("POUR(1,2) "); 62 } 63 break; 64 case 5: 65 { 66 printf("POUR(2,1) "); 67 } 68 break; 69 } 70 } 71 } 72 73 74 void f1(node& n) 75 { 76 n.aa=0; 77 } 78 void f2(node& n) 79 { 80 n.aa=a; 81 } 82 void f3(node& n) 83 { 84 n.bb=0; 85 } 86 void f4(node&n) 87 { 88 n.bb=b; 89 } 90 void f5(node&n) 91 { 92 if(b-n.bb<n.aa) 93 { 94 n.aa=n.aa-(b-n.bb); 95 n.bb=b; 96 } 97 else 98 { 99 n.bb+=n.aa; 100 n.aa=0; 101 } 102 } 103 void f6(node&n) 104 { 105 if(a-n.aa<n.bb) 106 { 107 n.bb=n.bb-(a-n.aa); 108 n.aa=a; 109 } 110 else 111 { 112 n.aa+=n.bb; 113 n.bb=0; 114 } 115 } 116 void(*fun[6])(node&n)={f1,f2,f3,f4,f5,f6};//函数指针数组,保存六个函数 117 118 119 int main() 120 { 121 while(~scanf("%d%d%d",&a,&b,&c)) 122 { 123 memset(fl,0,sizeof(fl));//标记数组,表示一种状态是否出现过 124 int front=0; 125 int tail=0; 126 nod[tail++]=node(0,0,-1,-1,0);//构造函数的用处 127 fl[0][0]=1; 128 int res; 129 int res_loc=-1; 130 while(front<tail) 131 { 132 node nd=nod[front++]; 133 if(nd.aa==c||nd.bb==c) 134 { 135 res=nd.level;//res记录得到结果时候的深度 136 res_loc=front-1;//表示得到的结果在数组中是第几个 137 break; 138 } 139 for(int i=0;i<6;i++)//进行六种操作,每次调用函数数组中的一个函数 140 { 141 node nt=nd; 142 fun[i](nt);//调用第i个函数 143 if(fl[nt.aa][nt.bb]==0) 144 { 145 fl[nt.aa][nt.bb]=1; 146 nod[tail++]=node(nt.aa,nt.bb,front-1,i,nt.level+1);//依然是构造函数的应用 147 } 148 } 149 } 150 if(res_loc==-1) 151 { 152 printf("impossible "); 153 continue; 154 } 155 printf("%d ",res); 156 output(res_loc); 157 } 158 return 0; 159 }