八数码

原题:八数码

在八数码中,估价函数就是所有数字在state中的位置与目标位置end中的位置的曼哈顿距离之和,即:

[f(state) = sumlimits^8_{i = 1} ( |state \_x_i - end \_x_i | + |state \_y_i - end \_y_i |) ]

对于八数码问题有个结论:

八数码逆序对必须是偶数才有解,因为每次左右移动都不会改变逆序对的个数,只有上下移动才会增加或者减少两个逆序对,所以如果逆序对是奇数那我们无论如何都无解。


#include <bits/stdc++.h>

using namespace std;

typedef pair<int, string> PIS;

int f(string str) {
	int res = 0;
	for (int i = 0; i < str.size(); i++) {
	    if (str[i] != 'x') {
	        int t = str[i] - '1';
		    res += abs(i / 3 - t / 3) + abs(i % 3 - t % 3);   
	    }
	}
	
	return res;
}

string bfs(string start) {
	int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
	string end = "12345678x";
	char op[] = "urdl";
	
	priority_queue<PIS, vector<PIS>, greater<PIS>> heap;
	unordered_map<string, int> dist;
	unordered_map<string, pair<char, string>> prev;
	
	heap.push({0 + f(start), start});
	dist[start] = 0;
	
	while (heap.size()) {
		auto t = heap.top();
		heap.pop();
		
		string state = t.second;
		
		if (state == end) break; 
		
		int x, y;
		for (int i = 0; i < state.size(); i++) {
			if (state[i] == 'x') {
				x = i / 3, y = i % 3;
				break;
			}
		}
		
		string source = state;
		for (int i = 0; i < 4; i++) {
			int a =  x + dx[i], b = y + dy[i];
			if (a >= 0 && a < 3 && b >= 0 && b < 3) {
				swap(state[x * 3 + y], state[a * 3 + b]);
				if (!dist.count(state) || dist[state] > dist[source] + 1) {
					dist[state] = dist[source] + 1;
					prev[state]	= {op[i], source};
					heap.push({dist[state] + f(state), state});
				}
				swap(state[x * 3 + y], state[a * 3 + b]);
			}
		}
	}
	
	string res = "";
	
	while (end != start) {
		res += prev[end].first;
		end = prev[end].second;
	}

	reverse(res.begin(), res.end());
	
	return res;
}

int main() {
	string start, str;
	char c;
	while (cin >> c) {
		start += c;
		if (c != 'x') str += c;
	}
	
	int cnt = 0;
	for (int i = 0; i < str.size(); i++) {
		for (int j = i; j < str.size(); j++) {
			if (str[i] - '0' > str[j] - '0') cnt++; 
		}
	}
	
	if (cnt & 1) puts("unsolvable");
	else {
		cout << bfs(start) << endl;	
	}
	
    return 0;
}
原文地址:https://www.cnblogs.com/ZhengLijie/p/15127349.html