Pots
直接上中文
Descriptions:
给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作
FILL(i) 将第i个容器从水龙头里装满(1 ≤ i ≤ 2);
DROP(i) 将第i个容器抽干
POUR(i,j) 将第i个容器里的水倒入第j个容器(这次操作结束后产生两种结果,一是第j个容器倒满并且第i个容器依旧有剩余,二是第i个容器里的水全部倒入j中,第i个容器为空)
现在要求你写一个程序,来找出能使其中任何一个容器里的水恰好有C升,找出最少操作数并给出操作过程
Input
有且只有一行,包含3个数A,B,C(1<=A,B<=100,C<=max(A,B))
Output
第一行包含一个数表示最小操作数K
随后K行每行给出一次具体操作,如果有多种答案符合最小操作数,输出他们中的任意一种操作过程,如果你不能使两个容器中的任意一个满足恰好C升的话,输出“impossible”
Sample Input
3 5 4
Sample Output
6 FILL(2) POUR(2,1) DROP(1) POUR(2,1) FILL(2) POUR(2,1)
题目链接:
https://vjudge.net/problem/POJ-3414
bfs优先队列就OK了,分6种情况讨论入队,具体题解都在代码上,注意看注释
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define ME0(x) memset(x,0,sizeof(x)) using namespace std; int a,b,c; int flag=0;//初始化不能成功 int total=0;//总共操作了几次,也是每个操作步骤的下标 int id[105*105];//保存正确路径的下标 int vis[105][105];//标记状态是否入队过 char op[][10]={"0","FILL(1)","FILL(2)", "DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};//最后的输出 struct node { int no;//当前下标 int k1,k2;//杯中剩余的水 int op;//操作 int step;//步数 int pre;//前一步的下标 bool operator<(const node &c)const//步数小的先出队 { return step>c.step; } }; priority_queue<node>q; node now,next; vector<node> v; void print(int i)//输出格式 { int j=0; while(v[i].no) { id[j++]=v[i].no;//储存正确路径的下标 i=v[i].pre; } for(i=j-1; i>=0; i--)//按照下标输出操作 { cout<<op[v[id[i]].op]<<endl; } } void bfs() { now.k1=0,now.k2=0,now.op=0,now.pre=0,now.step=0,now.no=0; vis[now.k1][now.k2]=1; q.push(now); v.push_back(now); while(!q.empty()) { now=q.top(); q.pop(); if(now.k1==c||now.k2==c)//满足条件 { flag=1; cout<<now.step<<endl;//输出步数 print(now.no);//输出格式 break; } for(int i=1; i<=6; i++) { if(i == 1) //fill(1) { next.k1 = a; next.k2 = now.k2; } else if(i == 2) //fill(2) { next.k1 = now.k1; next.k2 = b; } else if(i == 3) //drop(1) { next.k1 = 0; next.k2 = now.k2; } else if(i == 4) // drop(2); { next.k1 = now.k1; next.k2 = 0; } else if(i == 5) //pour(1,2) { if(now.k1+now.k2 <= b) //如果不能够装满 b { next.k1 = 0; next.k2 = now.k1+now.k2; } else //如果能够装满 b { next.k1 = now.k1+now.k2-b; next.k2 = b; } } else if(i == 6) // pour(2,1) { if(now.k1+now.k2 <= a) //如果不能够装满 a { next.k1 = now.k1+now.k2; next.k2 = 0; } else //如果能够装满 b { next.k1 = a; next.k2 = now.k1+now.k2-a; } } next.op=i; if(!vis[next.k1][next.k2]) { total++; next.no=total; vis[next.k1][next.k2]=1; next.step=now.step+1; next.pre=now.no; v.push_back(next); q.push(next); } } } if(flag==0) cout<<"impossible"<<endl; } int main() { ME0(vis); cin>>a>>b>>c; bfs(); }