zoukankan      html  css  js  c++  java
  • 康拓展开

    可以用于将排列hash为第多少个排列
    分解为x=an(n-1)!+ai(i-1)!+a1*0!
    ai为还未出现的第几大(从0开始)
    逆康拓可以用于找第多少个排列,获取不断对阶乘辗转相除的余数作为排列中的第几大
    八数码,astar
    h为预估为总的离自己曼哈顿距离和
    利用优先队列对g+h排序
    利用康托展开hash或者直接用map保存状态
    一开始利用去掉空块的逆序数的移动一次逆序数改变为偶数判断是否有解
    左右移动不变逆序数不变,上下移动为移动到相邻两个前后
    逆序数相邻移动改变逆序数为1两次同向移动为2

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 10;
    int d[N][N];
    int a[N];
    map<int,int> p;
    void Init() {
    	for (int i = 0;i < 3;i++)
    		for (int j = 0;j < 3;j++) {
    			for (int x = 0;x < 3;x++) {
    				for (int y = 0;y < 3;y++) {
    					d[i * 3 + j+1][x * 3 + y+1] = abs(x - i) + abs(y - j);
    				}
    			}
    		}
    }
    int CalDis(int state){
    	int s = 0;
    	int k = 0;
    	while(state){
    		s += d[9 - k][state % 10];
    		state /= 10;
    		k++;
    	}
    	return s;
    }
    map<int,int> mp;
    int GetState(int *a) {
    	int s = 0;
    	for (int i = 1;i <= 9;i++) {
    		s = s * 10 + a[i];
    	}
    	return s;
    }
    bool GetNState(int state,int& nstate,int x, int y, int nx, int ny) {
    	int k1 = 8-(x * 3 + y-4);
    	int k2 = 8-(nx * 3 + ny-4);
    	int x1 = 1, x2 = 1, d1 = 0, d2 = 0;
    	for (int i = 0;i <= max(k1, k2);i++) {
    		if (i == k1) {
    			d1 = state / x1 % 10;
    		}
    		if (i == k2) {
    			d2 = state / x2 % 10;
    		}
    		if (i < k1) {
    			x1 *= 10;
    		}
    		if (i < k2) {
    			x2 *= 10;
    		}
    	}
    	nstate = state - (x1*d1 + x2*d2) + (x1*d2 + x2*d1);
    	return true;
    }
    bool GetXY(int state, int& x, int& y) {
    	int k=8;
    	while (state%10!=9) {
    		state /= 10;
    		k--;
    	}
    	x = k / 3+1;
    	y = k % 3+1;
    	return true;
    }
    int dx[] = { 1,0,-1,0 };
    int dy[] = { 0,1,0,-1 };
    bool ok(int i, int j) {
    	if (i <= 0 || j <= 0 || i>3 || j>3)return false;
    	return true;
    }
    struct Node {
    	int state, edis;
    	bool operator <(const Node& rhs)const {
    		return edis > rhs.edis;
    	}
    };
    void Astar(int state) {
    	int x, y;
    	priority_queue<Node>q;
    	q.push(Node{ state,CalDis(state) });
    	while (!q.empty()) {
    		Node node = q.top();q.pop();
    		int state = node.state;
    		if (state == 123456789) {
    			return;
    		}
    		GetXY(state, x, y);
    		for (int i = 0;i < 4;i++) {
    			int nx = x + dx[i];
    			int ny = y + dy[i];
    			if (ok(nx, ny)) {
    				int nstate;
    				GetNState(state, nstate, x, y, nx, ny);
    				if (!mp.count(nstate)) {
    					mp[nstate] = mp[state] + 1;
    					q.push(Node{ nstate,mp[nstate]+CalDis(nstate) });
    					p[nstate] = state;
    				}
    				else {
    					if (mp[nstate] > mp[state] + 1) {
    						mp[nstate] = mp[state] + 1;
    						q.push(Node{ nstate,mp[nstate]+CalDis(nstate) });
    						p[nstate] = state;
    					}
    				}
    
    			}
    		}
    	}
    }
    char CalMove(int state, int nstate) {
    	int x, y, nx, ny;
    	GetXY(state, x, y);
    	GetXY(nstate, nx, ny);
    	if (x < nx) { return 'd'; }
    	if (x > nx) { return 'u'; }
    	if (y < ny) { return 'r'; }
    	if (y > ny) { return 'l'; }
    }
    void print(int state,int nstate) {
    	if (p[state] != -1)
    		print(p[state],state);
    	printf("%c",CalMove(state, nstate));
    }
    bool CanSolve(int state) {
    	int s = 0;
    	int b[10] = { 0 };
    	while (state) {
    		int x = state % 10;
    		if (x != 9) {
    			s += (8 - state % 10) - b[state % 10];
    			for (int i = 1;i < state % 10;i++)
    				b[i]++;
    		}
    		state /= 10;
    	}
    	return (s % 2==0);
    }
    void solve() {
    	int state = GetState(a);
    	if (!CanSolve(state)) {
    		printf("unsolvable
    ");
    		return;
    	}
    	p[state] = -1;
    	mp[state] = 0;
    	Astar(state);
    	if(p[123456789]!=-1)
    		print(p[123456789],123456789);
    	printf("
    ");
    }
    int main()
    {
    	Init();
    	int b, i, j, s = 1, sum = 0;
    	char x[5];
    	while (scanf("%s",x)!=EOF)
    	{
    		p.clear();
    		mp.clear();
    		a[1] = x[0] - '0';
    		for (int i = 2;i <= 9;i++) {
    			scanf("%s", x);
    			a[i] = x[0] - '0';
    		}
    		for (int i = 1;i <= 9;i++) {
    			if (a[i] == 'x' - '0')
    				a[i] = 9;
    		}
    		solve();
    	}
    }
    
  • 相关阅读:
    vs2010配置驱动开发
    寒假训练 npuctf_2020_bad_guy(11/250)利用overlap与fastbin attack来篡改fd指针,从而通过stdout达到泄露libc
    寒假训练 [OGeek2019]bookmanager(10/250)
    寒假训练 npuctf_2020_level2(9/250)将heap分配到bss上,从而满足程序条件
    寒假训练 npuctf_2020_level2(8/250)修改ebp链来间接修改返回地址
    Windows XP源码跟踪
    寒假训练 houseoforange_hitcon_2016(7/250)
    寒假训练 jarvisoj_level6_x64(6/250)
    寒假训练 de1ctf_2019_weapon(5/250)
    glibc源码逆向——fwrite函数
  • 原文地址:https://www.cnblogs.com/HaibaraAi/p/5042952.html
Copyright © 2011-2022 走看看