总结一下这题的解题步骤:
1.将问题抽象成某种模型,比如这题就是找出一个有d的状态,且要倒水量最小,平时写的都是路径最小
,用的是普通队列,这题要把倒水量最小考虑进去就需要用优先队列
即:用优先队列的就是在队列中不断找出倒水量最小的状态,然后判断是否一个容器中的水为d
普通队列可以用来求最短路径长度,即不断的找出离原始状态最近的状态,判断是否有一个容器中的水为d
所以其实也可以用优先队列来找最短路径只要优先队列是以路径长度来排序的即可
2.写出更新状态的算法,最简单的就是枚举出所有可能的情况完全不考虑重复的问题,模拟倒水的过程
3.用具体的例子验证一下算法的正确性
4.和之前学过的知识做比较,比如以后要是又找个什么路径,都其实可以尝试用优先队列
#include <iostream> #include <cstdio> #include <queue> using namespace std; const int maxn=3; int cap[maxn]; const int maxd=210; int vis[maxd][maxd][maxd]; struct Node { int v[3]; int dist; bool operator< (const Node& rhs) const { return dist > rhs.dist; } }; bool matchp(Node n,int d) { if(n.v[0]==d || n.v[1]==d || n.v[2]==d) return true; else return false; } int bfs(int a,int b,int c,int& d) { memset(vis,0,sizeof(vis)); priority_queue<Node> q; Node st; st.v[0]=0; st.v[1]=0; st.v[2]=cap[2]; st.dist=0; q.push(st); while(!q.empty()) { Node nod=q.top(); q.pop(); if(matchp(nod,d)) return nod.dist; //update for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(i!=j) { Node newnod=nod; if(newnod.v[i]>cap[j]-newnod.v[j]) { newnod.v[i]-=cap[j]-newnod.v[j]; newnod.dist+=cap[j]-newnod.v[j]; newnod.v[j]=cap[j]; } else { newnod.v[j]+=newnod.v[i]; newnod.dist+=newnod.v[i]; newnod.v[i]=0; } if(vis[newnod.v[0]][newnod.v[1]][newnod.v[2]]==1) continue; vis[newnod.v[0]][newnod.v[1]][newnod.v[2]]=1; q.push(newnod); } } return bfs(a,b,c,--d); } int main() { int a,b,c,d; cin>>a>>b>>c>>d; cap[0]=a; cap[1]=b; cap[2]=c; int ans=bfs(a,b,c,d); printf("%d %d\n",ans,d); return 0; }
时间: 2024-12-17 12:55:22