HDU - 1043 Eight 【反向BFS打表】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/86823038

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043

因为状态不多,在样例不多的情况下,直接bfs也是能过的(POJ),但是对于样例多的HDU,需要把所有可能的结果都预处理一遍存起来,要的时候直接输出结果,就能快很多。

网上很多代码都有用康托展开做空间优化,不用康托展开优化,用一个map存结果,也是能过的,下面写了两个。

要注意的是,你bfs是反向扩展的,所以,方向和顺序都要反过来。

如果你存的结果也是char类型的,记的在后面补上 '\0'。

具体康托展开的原理可以参考我之前写的博客:https://blog.csdn.net/godleaf/article/details/86818162

#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <cstdio>

using namespace std;

const int INF = 0x3f3f3f3f;
const int Maxn = 200+10;

struct Node {
	char state[10], ans[100], cnt, pos;
};

char s[10] = "12345678x";
map<string, pair <string, bool> > vis;
int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} };
char ch[5] = "lrud";

void bfs() {
	vis.clear();
	queue<Node> qu;

	Node tmp;
	for(int i = 0; i < 9; ++i) if(s[i] == 'x') {
		tmp.pos = i; break;
	}
	tmp.cnt = -1; memcpy(tmp.state, s, sizeof(tmp.state));
	vis[s].second = true; vis[s].first = "rl";
	qu.push(tmp);

	while (!qu.empty()) {
		tmp = qu.front(); qu.pop();

		int pi = tmp.pos/3, pj = tmp.pos%3, ii, jj;
		Node now;

		for(int i = 0; i < 4; ++i) {
			ii = pi+dir[i][0], jj = pj+dir[i][1];
			if(ii < 0 || ii > 2 || jj < 0 || jj > 2) continue;

			now = tmp;
			swap(now.state[ii*3+jj], now.state[now.pos]);
			if(vis[now.state].second) continue;
			vis[now.state].second = true;
			now.pos = ii*3+jj;
			now.ans[++now.cnt] = ch[i];
			now.ans[now.cnt+1] = '\0';
			vis[now.state].first = now.ans;
			qu.push(now);
		}
	}
}

int main(void)
{
	int cnt; char b[30];
	bfs();
	while (gets(b)){
		cnt = 0;
		memset (s, 0, sizeof(s));
		for(int i = 0; i < strlen(b); ++i) if((b[i] >= '1' && b[i] <= '8') || b[i] == 'x') s[cnt++] = b[i];
		if(vis[s].second) {
            string tmp = vis[s].first;
            for(int i = tmp.size()-1; i >= 0; --i) cout << tmp[i];
            cout << endl;
		}
		else cout << "unsolvable" << endl;
	}
	return 0;
}
#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int Maxn = 1e6+10;

char s[10] = "123456780";
char ans[Maxn][50];
int dir[4][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0} }, n[15];
char op[5] = "lrud";
bool vis[Maxn];

int cantor(char* ss) {
    int ret = 0;
    for(int i = 0; i < 9; ++i) {
        int cnt = 0;
        for(int j = i+1; j < 9; ++j) {
            if(ss[j] < ss[i]) cnt++;
        }
        ret += cnt*n[8-i];
    }
    return ret;
}

void decantor(int num, char *ss, int &pos) {
   int p = 0; bool v[10];
   memset(v, false, sizeof(v));
   for(int i = 8; i >= 0; --i) {
        int cnt = 0, tmp = num/n[i];
        num %= n[i];
        for(int j = 0; j < 9; ++j) {
            if(v[j]) continue;
            if(cnt == tmp) {
                if(j == 0) pos = p;
                ss[p++] = j+'0';
                v[j] = true;
                break;
            }
            cnt++;
        }
   }
   ss[p] = '\0';
}

void bfs() {
	queue<int> qu;
	memset(vis, false, sizeof(vis));
	int tmp = cantor(s);
	qu.push(tmp);
	vis[tmp] = true;

	while(!qu.empty()) {
        int num = qu.front(); qu.pop();

        for(int i = 0; i < 4; ++i) {
            char ch[10]; int pos, pi, pj;
            decantor(num, ch, pos);
            pi = pos/3; pj = pos%3;
            pi += dir[i][0]; pj += dir[i][1];
            if(pi < 0 || pi > 2 || pj < 0 || pj > 2) continue;
            swap(ch[pi*3+pj], ch[pos]);
            int now = cantor(ch);
            if(vis[now]) continue;
            vis[now] = true;
            memcpy(ans[now], ans[num], sizeof(ans[now]));
            int len = strlen(ans[now]);
            ans[now][len] = op[i]; ans[now][len+1] = '\0';
            qu.push(now);
        }
	}
}

int main(void)
{
	int cnt; char b[30];
	n[1] = n[0] = 1;
	for(int i = 2; i <= 10; ++i) n[i] = n[i-1]*i;
	bfs();

	while (gets(b)){
		cnt = 0;
		memset (s, 0, sizeof(s));
		for(int i = 0; i < strlen(b); ++i) {
            if((b[i] >= '1' && b[i] <= '8')) s[cnt++] = b[i];
            else if(b[i] == 'x') s[cnt++] = '0';
		}

		int tmp = cantor(s);
		if(vis[tmp]) {
            for(int i = strlen(ans[tmp])-1; i >= 0; --i) cout << ans[tmp][i];
            cout << endl;
		}
		else cout << "unsolvable" << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/86823038