题目: HUD POJ
这就是我们以前玩过的一种游戏,题目是3*3的格子有一个是空的,把他们还原成特定的顺序.
有人说没有做过这个题目的人生是不完整的?
我写了一发纯暴力,map<string, int> 判重,map<string , string > 记录路径 竟然让我在HDU水过了,代码太挫了就不贴了。
其实可以发现 这样判重是非常耗时,而且 显然可以找到一个hash关系的,因为一共有9!种排列方式 ,如果能找到一种双射的话,无论是判重,还有记录路径都会优化很多的。
如果我们可以对于每一种排列求出它在所有排列中字典序排列中的位置,就可以找到双射了。
其实是有的------ 康托展开
对于记录路径,可以记录当前的方向和上一步的状态,这样可以大大节省内存。
对于HDU 给了5s, 多组数据,可以打表,因为终态确定,可以从终态出发BFS,对于每组数据,就成了询问了。
对于POJ 1s,单组数据, 打表就没有了意义,可以按照他给的状态为起始状态BFS。
HDU:
这就是我们以前玩过的一种游戏,题目是3*3的格子有一个是空的,把他们还原成特定的顺序.
有人说没有做过这个题目的人生是不完整的?
我写了一发纯暴力,map<string, int> 判重,map<string , string > 记录路径 竟然让我在HDU水过了,代码太挫了就不贴了。
其实可以发现 这样判重是非常耗时,而且 显然可以找到一个hash关系的,因为一共有9!种排列方式 ,如果能找到一种双射的话,无论是判重,还有记录路径都会优化很多的。
如果我们可以对于每一种排列求出它在所有排列中字典序排列中的位置,就可以找到双射了。
其实是有的------ 康托展开
对于记录路径,可以记录当前的方向和上一步的状态,这样可以大大节省内存。
对于HDU 给了5s, 多组数据,可以打表,因为终态确定,可以从终态出发BFS,对于每组数据,就成了询问了。
对于POJ 1s,单组数据, 打表就没有了意义,可以按照他给的状态为起始状态BFS。
还有很多更优的解法吧,慢慢补上吧。
POJ:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
#define N 400000
char ss[3];
int fac[11], dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
char dd[5] = {"rldu"};
struct node
{
int num, zero, x[11];
};
node S, T;
bool vis[N];
vector<char > save;
struct nn
{
char th;
int last;
}mm[N];
int cal(int x[])
{
int ret = 0;
for(int i = 1; i <= 9; i++) {
int cou = 0;
for(int j = i+1; j <= 9; j++) {
if(x[j] < x[i]) cou++;
}
ret += cou * fac[9 - i ];
}
return ret;
}
int change(node &in, int dx, int dy)
{
int x = (in.zero - 1) /3 + 1;
int y = (in.zero - 1) %3 + 1;
int nx = x + dx;
int ny = y + dy;
if(nx < 1 || nx > 3 || ny < 1 || ny > 3) return 0;
int ww = (nx - 1) * 3 + ny;
swap(in.x[in.zero], in.x[ww]);
in.num = cal(in.x);
in.zero = ww;
return 1;
}
int bfs()
{
queue<node > Q;
Q.push(S);
memset(vis, 0, sizeof(vis));
vis[S.num] = 1;
mm[S.num].last = -1;
node now, next;
while(!Q.empty()) {
now = Q.front(); Q.pop();
if(now.num == T.num) return 1;
for(int i = 0; i< 4; i++) {
next = now;
int tmp = change(next, dir[i][0], dir[i][1]);
if(!tmp) continue;
if(vis[next.num]) continue;
vis[next.num ] = 1;
mm[next.num].last = now.num;
mm[next.num].th = dd[i];
Q.push(next);
}
}
return 0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
fac[0] = 1;
for(int i = 1; i <= 10; i++) fac[i] = fac[i-1] * i;
int s[11];
for(int i = 1; i <= 9; i++) T.x[i] = i;
T.zero = 9;
T.num = cal(T.x);
while(scanf("%s", ss) != EOF) {
int tmp , zero ;
if(ss[0] =='x') tmp = 9, zero = 1;
else tmp = ss[0] - '0';
S.x[1] = tmp;
for(int i = 1; i <= 8; i++) {
scanf("%s", ss);
if(ss[0] == 'x') tmp = 9, zero = i+1;
else tmp = ss[0] - '0';
S.x[i+1] = tmp;
}
S.zero = zero;
S.num = cal(s);
int ans = bfs();
if(ans == 1) {
int gg = T.num;
save.clear();
for(int tmp = gg; mm[tmp].last != -1; tmp = mm[tmp].last) save.push_back(mm[tmp].th);
for(int i = save.size() -1 ; i >= 0; i--) printf("%c", save[i]); puts("");
}
else puts("unsolvable");
}
return 0;
}
HDU:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define INF 1000000000
#define N 400000
char ss[3];
int fac[11], dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
char dd[5] = {"lrud"};
struct node
{
int num, zero, x[11];
};
node S;
bool vis[N];
struct nn
{
char th;
int last;
}mm[N];
int cal(int x[])
{
int ret = 0;
for(int i = 1; i <= 9; i++) {
int cou = 0;
for(int j = i+1; j <= 9; j++) {
if(x[j] < x[i]) cou++;
}
ret += cou * fac[9 - i ];
}
return ret;
}
int change(node &in, int dx, int dy)
{
int x = (in.zero - 1) /3 + 1;
int y = (in.zero - 1) %3 + 1;
int nx = x + dx;
int ny = y + dy;
if(nx < 1 || nx > 3 || ny < 1 || ny > 3) return 0;
int ww = (nx - 1) * 3 + ny;
swap(in.x[in.zero], in.x[ww]);
in.num = cal(in.x);
in.zero = ww;
return 1;
}
void bfs()
{
queue<node > Q;
Q.push(S);
vis[S.num] = 1;
mm[S.num].last = -1;
node now, next;
while(!Q.empty()) {
now = Q.front(); Q.pop();
for(int i = 0; i< 4; i++) {
next = now;
int tmp = change(next, dir[i][0], dir[i][1]);
if(!tmp) continue;
if(vis[next.num]) continue;
vis[next.num ] = 1;
mm[next.num].last = now.num;
mm[next.num].th = dd[i];
Q.push(next);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
fac[0] = 1;
for(int i = 1; i <= 10; i++) fac[i] = fac[i-1] * i;
int s[11];
for(int i = 1; i <= 9; i++) S.x[i] = i;
S.zero = 9;
S.num = cal(S.x);
bfs();
while(scanf("%s", ss) != EOF) {
int tmp ;
if(ss[0] =='x') tmp = 9;
else tmp = ss[0] - '0';
s[1] = tmp;
for(int i = 1; i <= 8; i++) {
scanf("%s", ss);
if(ss[0] == 'x') tmp = 9;
else tmp = ss[0] - '0';
s[i+1] = tmp;
}
int gg = cal(s);
if(!vis[gg]) printf("unsolvable\n");
else {
for(int t = mm[gg].last, g = gg; t != -1; t = mm[t].last) {
printf("%c", mm[gg].th);
gg = t;
}
puts("");
}
}
return 0;
}