zoukankan      html  css  js  c++  java
  • 八数码

    原题:八数码

    在八数码中,估价函数就是所有数字在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;
    }
    
  • 相关阅读:
    P1903 [国家集训队]数颜色 / 维护队列 莫对算法
    P1016 旅行家的预算 模拟 贪心
    P3948 数据结构 差分数组
    乘法逆元 模板
    二分法 最大化平均值
    HDU5213 Lucky 莫队算法 容斥定理
    P1083 借教室 差分数组
    发布订阅、redis的配置文件、redis的主从、redis的持久化、
    nosql、redis、性能测试、命令相关、redis的数据类型string、list、hash、set、zset、
    nginx的日志、禁止访问、反向代理、权重、nginx location匹配规则、location分离、WSGI、
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/15127349.html
Copyright © 2011-2022 走看看