搜尋初探 Pots POJ - 3414
阿新 • • 發佈:2018-11-19
做這題的時候,沒有思路,覺得暴力的話,狀態可能會爆炸。
但是每一個狀態,最多隻有六個後繼狀態,並且資料量很小,可以使用bfs列舉得出最短路
。
搜尋的時候,怎麼判斷該狀態
是否已經經過了呢,可以使用 visit陣列。因為每個瓶子最大容量是 30 兩個瓶子的組合才 900 ,容量空間非常小。
所以這題最重要的就是關注到狀態轉移
和 visit 陣列
。
另外還有一點就是學習了如何列印 bfs路徑
。
可以使用一維陣列儲存所有的列舉過的狀態,然後使用鏈式前向星的思想,記錄每一個節點的前驅結點。
關鍵點在於每一個 節點的父親節點是唯一的,每一個節點的孩子節點卻有多個。
這是一個多叉圖,而不是網狀圖。
#include<iostream> #include<vector> #include<queue> #include<string> #include<cstring> using namespace std; int va,vb,vc; struct node { int father; int a; int b; int x; //操作幾 int y; //對誰操作 }num[10005]; vector<int> path; queue<int> qu; int vis[105][105]; int counts; int flag; void bfs() { counts=0; num[counts].a = 0; num[counts].b = 0; num[counts].father = -1; qu.push(counts); vis[num[counts].a][num[counts].b] = 1; //如果這個點已經進入佇列就不用再進隊了 因為在此之前 一定步數更少 counts++; while(!qu.empty()) { int p = qu.front(); node f = num[p]; qu.pop(); if(f.a==vc||f.b==vc) { flag =p; break; } //操作 a //填滿 if(f.a< va&&vis[va][f.b]!=1) { num[counts].a = va; num[counts].b = f.b; num[counts].father =p ; num[counts].x = 1; num[counts].y = 0; qu.push(counts); vis[num[counts].a][num[counts].b]=1; counts++; } //清空 if(f.a >0 &&vis[0][f.b]!=1) { num[counts].a = 0; num[counts].b = f.b; num[counts].father = p; num[counts].x = 2; num[counts].y = 0; qu.push(counts); vis[num[counts].a][num[counts].b]=1; counts++; } // a -> b if(f.a >0 &&f.b<vb) { int aa; int bb; if(f.a > vb-f.b) { aa = f.a -vb+f.b; bb = vb; } else { aa = 0; bb = f.a+f.b; } if(vis[aa][bb]!=1) { num[counts].a = aa; num[counts].b = bb; num[counts].father = p; num[counts].x = 3; num[counts].y = 0; qu.push(counts); vis[num[counts].a][num[counts].b]=1; counts++; } } //操作 b //填滿 if(f.b<vb &&vis[f.a][vb]!=1) { num[counts].a = f.a; num[counts].b = vb; num[counts].father = p; num[counts].x = 1; num[counts].y = 1; qu.push(counts); vis[num[counts].a][num[counts].b]=1; counts++; } //清空 if(f.b >0 &&vis[f.a][0]!=1) { num[counts].a = f.a; num[counts].b = 0; num[counts].father = p; num[counts].x = 2; num[counts].y = 1; qu.push(counts); vis[num[counts].a][num[counts].b]=1; counts++; } // b -> a if(f.b >0 &&f.a<va) { int aa; int bb; if(f.b > va-f.a) { aa = va; bb = f.b - va+f.a; } else { aa = f.a+f.b; bb = 0; } if(vis[aa][bb]!=1) { num[counts].a = aa; num[counts].b = bb; num[counts].father = p; num[counts].x = 3; num[counts].y = 1; qu.push(counts); vis[num[counts].a][num[counts].b]=1; counts++; } } } while(!qu.empty())qu.pop(); } string op[3] = {"FILL","DROP","POUR"}; void shows(int i) { int x = num[i].x; int y = num[i].y; if(x==1) { if(y==0)cout<<"FILL(1)"<<endl; else cout<<"FILL(2)"<<endl; }else if(x==2){ if(y==0) cout<<"DROP(1)"<<endl; else cout<<"DROP(2)"<<endl; }else if(x==3){ if(y==0) cout<<"POUR(1,2)"<<endl; else cout<<"POUR(2,1)"<<endl; } } int main() { ios::sync_with_stdio(false); while(cin>>va>>vb>>vc) { flag =-1; memset(vis,0,sizeof(vis)); bfs(); if(flag == -1) { cout<<"impossible"<<endl; }else{ path.clear(); while(flag!=-1) { path.push_back(flag); flag = num[flag].father; } cout<<path.size()-1<<endl; for(int i = path.size()-1;i>=0;i--) { shows(path[i]); } } } return 0; }