1. 程式人生 > 其它 >倒水問題(程式設計藝術與方法個人實驗)

倒水問題(程式設計藝術與方法個人實驗)

技術標籤:筆記

問題描述:給定2個沒有刻度容器,對於任意給定的容積,求出如何只用兩個瓶裝出L升的水,如果可以,輸出步驟,如果不可以,請輸出No Solution。

①實驗要求:
(1)求出如何只用兩個瓶裝出L升的水,如果可以,輸出步驟,如果不可以,請輸出No Solution.

題目分析:
這一題可以使用BFS的思想來做。

對於A、B兩個瓶子,在任何時刻,“倒水” 無非6種操作:
1.倒滿A;
2.倒滿B;
3.倒空A;
4.倒空B;
5.A往B倒;
6.B往A倒;

本題我沒用採用STL的佇列,通過在表示每個狀態的節點中加入父結點指標,當找到可行解時,通過父結點指標回溯,已達到輸出每一步的結果。同時對兩容器容積進行特判,因為如果不互質則無解。同時所量容積不能超過兩容器總體積之和。

接下來是程式碼實現:

#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <algorithm>

using namespace std;

typedef struct node Node;

struct node{
	int step;	//記錄上一節點所採取的步驟 
	int a;		//當前a容器的液體的體積 
	int b;		//當前b容器的液體的體積
	int pre;	//記錄父節點 
};

int a, b, L,
ans; //兩容器容積和所需體積 int visited[200][200]; //記錄該節點是否被訪問 vector<string> v; //不同的倒水策略 vector<Node> Ans; //用於儲存BFS節點 stack<Node> s; //用於輸出移動步驟 void initialize(){ //初始化所需資訊 v.push_back("a to b"); //step0 v.push_back("b to a"); //step1 v.push_back("Fill a"
); //step2 v.push_back("Fill b"); //step3 v.push_back("Empty a"); //step4 v.push_back("Empty b"); //step5 cout << "請輸入兩個容器的體積和所需液體體積:" << endl; cin >> a >> b >> L; cout << "容器的體積分別為: " << a << " " << b << endl; cout << "所需液體體積為:" << L << endl; Node n; //第一個節點,無父節點 n.pre = -1; n.a = 0; n.b = 0; n.step = -1; Ans.push_back(n); } bool rp(int a, int b){ int temp; if(a < b) swap(a, b); while(b){ temp = a % b; a = b; b = temp; } if(a == 1) return true; else return false; } int BFS(){ for(int i = 0; i < Ans.size(); i++){ Node p = Ans[i]; Node t; if(a + b < L) break; if(!rp(a,b)) break; if(p.a == L || p.b == L || (p.a + p.b == L)){ //找到可行解退出 ans = i; return 1; } if(p.a && p.b < b){ //a往b中倒水 if((p.b >= b - p.a) && !visited[p.a - b + p.b][b]){ //倒滿b後a有剩餘 t.a = p.a - b + p.b; t.b = b; t.pre = i; t.step = 0; Ans.push_back(t); } else if(!visited[0][p.b + p.a]){ //a沒有剩餘 t.a = 0; t.b = p.b + a; t.pre = i; t.step = 0; Ans.push_back(t); } } if(p.b && p.a < a){ //b往a中倒水 if((p.a >= a - p.b) && !visited[a][p.b - a + p.a]){ //倒完後b中有剩餘 t.a = a; t.b = p.b - a + p.a; t.pre = i; t.step = 1; Ans.push_back(t); } else if(!visited[p.a + p.b][0]){ //b沒有剩餘 t.a = p.a + p.b; t.b = 0; t.pre = i; t.step = 1; Ans.push_back(t); } } if(p.a < a && !visited[a][p.b]){ //倒滿a t.a = a; t.b = p.b; t.pre = i; t.step = 2; Ans.push_back(t); } if(p.b < b && !visited[p.a][b]){ //倒滿b t.a = p.a; t.b = b; t.pre = i; t.step = 3; Ans.push_back(t); } if(p.a && !visited[0][p.b]){ //清空a t.a = 0; t.b = p.b; t.pre = i; t.step = 4; Ans.push_back(t); } if(p.b && !visited[p.a][0]){ //清空b t.a = p.a; t.b = 0; t.pre = i; t.step = 5; Ans.push_back(t); } } return 0; } void show(){ int count = 1; Node q = Ans[ans]; while(q.pre != -1){ s.push(q); q = Ans[q.pre]; } while(!s.empty()){ q = s.top(); cout << "step " << count << " : "<< v[q.step] << endl; count++; s.pop(); } } int main(){ initialize(); if(!BFS()) cout << "No Solution!" << endl; else show(); return 0; }

執行結果示例:

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述