POJ3414 模擬倒水問題 BFS記錄路徑


臥槽!被struct折服了!以後就用它了!


題目概述:

這道題就是經典的倒水問題,不禁感慨一句以前需要人腦來做的東西現在直接計算機模擬就夠了。

給定三個數字,前兩個數字表示的是兩個桶的最大容量,第三個數字表達的是目標容量。一共有三種操作,分別是清空某桶,裝滿某桶,還有把一個桶裏面的水倒入另一個桶(如果會溢出就只能剛好倒滿,剩下的水留在自己的桶裏)。要求輸出最少的操作步數,並且要輸出操作方法。

算法思想:

因爲題目要求輸出的是最少操作步數,就想到了用BFS來枚舉各個狀態,而且其實可枚舉出來的狀態真的很少呀。

然後vis[][]這個數組記錄的是(i,j)這個水流組合現在有沒有出現過,這個其實不止起了優化的作用,而是保證程序可以終止,因爲假如輸入的數據是一個無法達到的數據的話,這個程序就會無限期枚舉下去,所以這個數組就是必要的。

知道了這些之後,仍然要解決路徑的問題,那麼解決方法就是開了一個struct,比我那個pair<int,int>不知高到哪裏去,因爲這個結構體可以存儲string,然後用string連接的操作就可以把所有操作記錄下來,實乃高招。哦也許讀者認爲很容易就想到但是我比較弱啊對不起 Orz。

希望代碼分層明顯的讀者可以自然寫幾個子函數,但是我當時覺得沒什麼必要就沒寫了。

代碼部分:

#include <iostream>
#include <queue>
#include <map>
#include <string>
using namespace std;
int a, b, c;
int vis[117][117] = { 0 };

struct node{
	int a_m, b_m;
	string step;
	node(int a_v, int b_v, string s_v) : a_m(a_v), b_m(b_v), step(s_v) {}
};

int main() {
	int a, b, c; bool flag = false;
	cin >> a >> b >> c;
	queue<node> q;
	node start(0, 0, "");
	node result(0, 0, "");
	q.push(start);
	vis[0][0] = 1;
	while (!q.empty()) {
		if (flag) break;
		node next = q.front();
		q.pop();
		if (next.a_m == c || next.b_m == c){
			flag = true;
			result = next;
		}
		if (next.a_m != 0) {
			node tmp = node(0, next.b_m, next.step + '1');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp); // We don't need to check whether this satisfy results
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m != 0) {
			node tmp = node(next.a_m, 0, next.step + '2');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp); 
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.a_m != a) {
			node tmp = node(a, next.b_m, next.step + '3');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m != b) {
			node tmp = node(next.a_m, b, next.step + '4');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.a_m != 0 && next.a_m+next.b_m <= b && next.b_m != b){
			node tmp = node(0, next.a_m + next.b_m, next.step + '5');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.a_m !=0 && next.a_m+next.b_m > b && next.b_m != b){
			node tmp = node(next.a_m+next.b_m-b, b, next.step + '5');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m !=0 && next.a_m+next.b_m <= a && next.a_m != a){
			node tmp = node(next.a_m + next.b_m, 0, next.step + '6');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m != 0 && next.a_m + next.b_m>a && next.a_m != a){
			node tmp = node(a, next.a_m+next.b_m-a, next.step + '6');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
	}

	if (!flag) cout << "impossible" << endl;
	else {
		cout << result.step.size() << endl;
		for (int i = 0; i < result.step.size(); i++){
			switch (result.step[i]) {
			case '1': cout << "DROP(1)" << endl; break;
			case '2': cout << "DROP(2)" << endl; break;
			case '3': cout << "FILL(1)" << endl; break;
			case '4': cout << "FILL(2)" << endl; break;
			case '5': cout << "POUR(1,2)" << endl; break;
			case '6': cout << "POUR(2,1)" << endl; break;
 			}
		}
	}
	
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章