bfs优先队列,把操作名称存入对应的下标,分六种情况讨论入队。
#include <iostream> #include <stdio.h> #include <queue> #include <vector> using namespace std; const int N = 110; int vis[N][N]; int point[N*N]; char option[][10] = {"#","FILL(1)","FILL(2)", "DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"}; //操作 struct node { int k1,k2; //k1:第一杯水 k2:第二杯水 int opnum; //当前操作 int nownum,prenum; //当前下标,前驱 int step; //操作步数 bool operator < (const node &c) const //步数小的优先出队 { return step > c.step; } }; priority_queue<node> q; vector<node> v; void print(int num) //打印路径 { int idx = 1; while(v[num].nownum) //存储下标 { point[idx++] = v[num].nownum; num = v[num].prenum; } int i = idx-1; while(i) //输出 { puts(option[v[point[i]].opnum]); i--; } } void bfs(int x,int y, int ans) { bool flag = true; node now; now.k1 = now.k2 = now.nownum = now.prenum = now.step = 0; q.push(now); vis[0][0] = 1; v.push_back(now); int idx = 0; while(!q.empty()) { now = q.top(); q.pop(); if(now.k1 == ans || now.k2 == ans) //满足条件 { flag =false; printf("%d ",now.step); //输出步数 print(now.nownum); //打印路径 break; } node Next; for(int i = 1; i <= 6; i++) { if(i == 1) //装满第一杯水 { Next.k1 = x; Next.k2 = now.k2; } if(i == 2) //装满第二杯水 { Next.k1 = now.k1; Next.k2 = y; } if(i == 3) //放干第一杯水 { Next.k1 = 0; Next.k2 = now.k2; } if(i == 4) //放干第二杯水 { Next.k1 = now.k1; Next.k2 = 0; } if(i == 5) //第一杯水倒入第二杯水中 { if(now.k1 + now.k2 <= y) //不能装满或刚好装满第二杯水 { Next.k1 = 0; Next.k2 = now.k1+now.k2; } else //能够装满且还有剩余 { Next.k1 = now.k1 + now.k2 - y; Next.k2 = y; } } if(i == 6) //第二杯水倒入一杯水中 { if(now.k1+now.k2 <= x) //不能或刚好装满 { Next.k1 = now.k1 + now.k2; Next.k2 = 0; } else //装满 { Next.k1 = x; Next.k2 = now.k1 + now.k2 - x; } } Next.opnum = i; //记录当前操作下标 if(!vis[Next.k1][Next.k2]) { idx++; //操作次数,当前的操作下标 Next.nownum = idx; vis[Next.k1][Next.k2] = 1; Next.step = now.step + 1; Next.prenum = now.nownum; v.push_back(Next); q.push(Next); } } } if(flag) puts("impossible"); } int main() { int A,B,C; scanf("%d %d %d",&A,&B,&C); bfs(A,B,C); return 0; }