题意:
求一个状态,使得距离初始状态步数最多
思路:
bfs+隐士图搜索
bfs取每个状态可能的移动,其中需要判断的是是否重复以及是否越界,最后一个自然是移动最多的
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<ctype.h>
#include<cstring>
using namespace std;
int ans;
const int maxn = 1000003;
int ori[9];
char d[5] = "UDLR";
int dx[5] = {-1, 1, 0, 0};
int dy[5] = {0, 0, -1, 1};
int st[maxn][9];
int Next[maxn];
int path[maxn];
int father[maxn];
int head[maxn];
int Hash(int *s) {
int sum = 0;
for(int i=0; i<9; i++)
sum = sum*10+s[i];
return sum%maxn;
}
bool judge(int s) {
int h = Hash(st[s]);
int u = head[h];
while(u) {
if(!memcmp(st[u], st[s], sizeof(st[s])))
return false;
u = Next[u];
}
Next[s] = head[h];
head[h] = s;
return true;
}
void bfs() {
father[0] = path[0] = -1;
memset(head, 0, sizeof(head));
memcpy(st[0], ori, sizeof(ori));
int front = 0, rear = 1;
judge(0);
while(front<rear) {
int i;
int *s = st[front];
for(i=0; i<9; i++) {
if(s[i] == 0) break;
}
int x = i/3, y = i%3;
int pos = i;
for(i=0; i<4; i++) {
int newx = x+dx[i];
int newy = y+dy[i];
int newp = newx*3+newy;
if(newx<3 && newx>=0 && newy<3 && newy>=0) {
int *news = st[rear];
memcpy(news, s, sizeof(int)*9);
news[newp] = 0;
news[pos] = s[newp];
if(judge(rear)) {
father[rear] = front;
path[rear] = i;
rear++;
}
}
}
front++;
}
ans = rear-1;
}
void print(int cur) {
if(cur) {
print(father[cur]);
printf("%c", d[path[cur]]);
}
}
int main() {
int kase;
char temp;
scanf("%d", &kase);
int cas = 1;
while(kase--) {
printf("Puzzle #%d\n", cas++);
for(int i=0; i<9; i++)
scanf("%d", &ori[i]);
bfs();
printf("%d %d %d\n%d %d %d\n%d %d %d\n", st[ans][0], st[ans][1], st[ans][2], st[ans][3],st[ans][4], st[ans][5], st[ans][6], st[ans][7], st[ans][8]);
print(ans);
printf("\n\n");
}
return 0;
}
所以最后一个自然是最远的状态