Pots(POJ - 3414)
演算法
BFS
1.這道題問的是給你兩個體積分別為A和B的容器,你對它們有三種操作,一種是裝滿其中一個瓶子,另一種是把其中一個瓶子的水都倒掉,還有一種就是把其中一個瓶子的水匯入另一個瓶子中(可能會有剩餘)。最後讓你輸出在能夠得出體積為C的水的情況下操作的最小次數並且把過程輸出。如果無法得出體積為C的水,則輸出“impossible”。
2.這個題主要涉及兩個點,一個是求出最小次數,還有一個就是把路徑輸出。對於這種有目標值的求最小次數問題,我們可以使用bfs解決。初始狀態是兩個瓶子都為空,最終狀態是其中一個瓶子中的水的容量達到了目標值C。在每個狀態下可以對瓶子進行上面描述的三種操作,細分下來其實只有6種操作,分別是:
- 將A瓶子裝滿水
- 將B瓶子裝滿水
- 將A瓶子中的水倒入B瓶子中
- 將B瓶子中的倒入A瓶子中
- 將A瓶子中的水全部抽走
- 將B瓶子中的水全部抽走
我們可以把每種狀態都放入到佇列中,當到達某種狀態時,就分別執行上面6個操作,同時需要注意做好每種狀態的標記,避免重複。
3.為了獲得路徑,我們可以把每次將新的狀態插入佇列中的同時用陣列記錄,可以用結構體來存放每個狀態,該結構體中除了當前A瓶和B瓶中水的容量這兩種屬性外,還要有它本身在陣列中的下標id,父狀態在陣列中的下標pre,到達此狀態時的最小步數steps。由於bfs的特殊性,我們可以認為當達到目標值時的steps為最小最優的(至於為什麼是最優的,我們可以簡單的想bfs因為是一層一層的搜尋的,所以可以認為第一個到達目標值的層數是最小的,當然前提是代價是一樣的,比如這裡每執行一步都表示一次,故可以用bfs實現,而如果執行每種操作的代價不同,就不能用bfs來實現了)。
C++程式碼
#include<iostream>
#include<queue>
#include<stack>
#include<cstdio>
using namespace std;
const int N = 1e6 + 10, M = 1e3;
int a, b, c;
bool st[M][M];
struct Status{
int ca, cb, pre;
int ope; //1表示裝滿A,2表示裝滿B,3表示A倒入B,4表示B倒入A,5表示倒掉A,6表示倒掉B
int steps;
int id;
Status(){
ca = 0, cb = 0, pre = -1;
ope = -1;
steps = 0;
id = 0;
}
}s[N];
int cnt;
//裝滿A
void fullA(Status& t)
{
t.ca = a;
t.ope = 1;
t.steps++;
t.id = cnt;
//s[cnt++] = t;
}
//倒掉A
void pourA(Status& t)
{
t.ca = 0;
t.ope = 5;
t.steps++;
t.id = cnt;
//s[cnt++] = t;
}
//裝滿B
void fullB(Status& t)
{
t.cb = b;
t.ope = 2;
t.steps++;
t.id = cnt;
//s[cnt++] = t;
}
//倒掉B
void pourB(Status& t)
{
t.cb = 0;
t.ope = 6;
t.steps++;
t.id = cnt;
// s[cnt++] = t;
}
//A倒入B
void pourA_B(Status& t)
{
if(t.ca >= b - t.cb)
{
t.ca -= b - t.cb;
t.cb = b;
}
else
{
t.cb += t.ca;
t.ca = 0;
}
t.ope = 3;
t.steps++;
t.id = cnt;
//s[cnt++] = t;
}
//B倒入A
void pourB_A(Status& t)
{
if(t.cb >= a - t.ca)
{
t.cb -= a - t.ca;
t.ca = a;
}
else
{
t.ca += t.cb;
t.cb = 0;
}
t.ope = 4;
t.steps++;
t.id = cnt;
//s[cnt++] = t;
}
void print(Status t)
{
cout << t.steps << endl;
stack<Status> sta;
sta.push(t);
while(true)
{
if(t.pre == -1) break;
t = s[t.pre];
sta.push(t);
}
while(sta.size())
{
Status tmp = sta.top();
sta.pop();
if(tmp.ope == 1)
puts("FILL(1)");
else if(tmp.ope == 2)
puts("FILL(2)");
else if(tmp.ope == 3)
puts("POUR(1,2)");
else if(tmp.ope == 4)
puts("POUR(2,1)");
else if(tmp.ope == 5)
puts("DROP(1)");
else if(tmp.ope == 6)
puts("DROP(2)");
}
}
void bfs()
{
Status tmp;
queue<Status> que;
que.push(tmp);
st[tmp.ca][tmp.cb] = true;
s[cnt++] = tmp;
while(que.size())
{
tmp = que.front();
que.pop();
//cout << "***" << tmp.ca << ", " << tmp.cb << endl;
if(tmp.ca == c || tmp.cb == c)
{
//cout << "**end** " << tmp.ca << " , " << tmp.cb << ", " << tmp.pre << endl;
//列印輸出
print(tmp);
return ;
}
//迴圈那六種情況
for(int i = 1; i <= 6; i++)
{
Status tmp1 = tmp;
//cout << "tmp*** " << tmp.ca << ", " << tmp.cb << endl;
if(i == 1)
{
if(tmp1.ca == a) continue;
fullA(tmp1);
if(!st[tmp1.ca][tmp1.cb])
{
tmp1.pre = tmp.id;
st[tmp1.ca][tmp1.cb] = true;
que.push(tmp1);
s[cnt++] = tmp1;
//cout << "tmp1**1* " << tmp1.ca << ", " << tmp1.cb << endl;
}
}
else if(i == 2)
{
if(tmp1.cb == b) continue;
fullB(tmp1);
if(!st[tmp1.ca][tmp1.cb])
{
tmp1.pre = tmp.id;
st[tmp1.ca][tmp1.cb] = true;
que.push(tmp1);
s[cnt++] = tmp1;
//cout << "tmp1**2* " << tmp1.ca << ", " << tmp1.cb << endl;
}
}
else if(i == 3)
{
if(!(tmp1.ca)) continue;
pourA_B(tmp1);
if(!st[tmp1.ca][tmp1.cb])
{
tmp1.pre = tmp.id;
st[tmp1.ca][tmp1.cb] = true;
que.push(tmp1);
s[cnt++] = tmp1;
//cout << "tmp1**3* " << tmp1.ca << ", " << tmp1.cb << endl;
}
}
else if(i == 4)
{
if(!(tmp1.cb)) continue;
pourB_A(tmp1);
if(!st[tmp1.ca][tmp1.cb])
{
tmp1.pre = tmp.id;
st[tmp1.ca][tmp1.cb] = true;
que.push(tmp1);
s[cnt++] = tmp1;
//cout << "tmp1**4* " << tmp1.ca << ", " << tmp1.cb << endl;
}
}
else if(i == 5)
{
if(!(tmp1.ca)) continue;
pourA(tmp1);
if(!st[tmp1.ca][tmp1.cb])
{
tmp1.pre = tmp.id;
st[tmp1.ca][tmp1.cb] = true;
que.push(tmp1);
s[cnt++] = tmp1;
//cout << "tmp1**5* " << tmp1.ca << ", " << tmp1.cb << endl;
}
}
else if(i == 6)
{
if(!(tmp1.cb)) continue;
pourB(tmp1);
if(!st[tmp1.ca][tmp1.cb])
{
tmp1.pre = tmp.id;
st[tmp1.ca][tmp1.cb] = true;
que.push(tmp1);
s[cnt++] = tmp1;
//cout << "tmp1**6* " << tmp1.ca << ", " << tmp1.cb << endl;
}
}
}
}
puts("impossible");
}
int main()
{
cin >> a >> b >> c;
bfs();
return 0;
}