题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1067
一开始看题目的时候,最苦恼的就是题目存在的状态数太多,空格可能存放的数字有28个,那么可能的状态就有 28!种,这个数目显然很大,所以不知道如何做。但事实上并不用都遍历一遍,虽然我知道,只要四个空格左边的数都是个位数为7的数,那么就可以肯定无解,这样能减少不少耗时,但是我没想到能减这么多。
所以用字符串压缩状态,并用map来记录遍历过的状态就行了。
#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 = 4e5+10;
struct Node {
char stat[80];
int step;
};
char Ed[80];
void bfs(char *ss) {
map<string, int> vis;
queue<Node> qu;
Node tmp;
memcpy(tmp.stat, ss, sizeof(tmp.stat));
tmp.step = 0;
qu.push(tmp);
vis[ss] = 1;
while (!qu.empty()) {
tmp = qu.front(); qu.pop();
if(!strcmp(tmp.stat, Ed)) {
printf("%d\n", tmp.step); return;
}
int len = strlen(tmp.stat);
for(int i = 0; i < len; i += 2) {
if(tmp.stat[i] == '0' && (tmp.stat[i-1] != '7' || tmp.stat[i-1] != '0')) {
Node now = tmp; now.step++;
for(int j = 0; j < len; j += 2) {
if(now.stat[j] == tmp.stat[i-2] && now.stat[j+1] == tmp.stat[i-1]+1) {
now.stat[i] = now.stat[j]; now.stat[i+1] = now.stat[j+1];
now.stat[j] = now.stat[j+1] = '0';
if(!vis[now.stat]) {
vis[now.stat] = 1; qu.push(now);
}
break;
}
}
}
}
}
printf("-1\n");
}
int main(void)
{
int T;
scanf("%d", &T);
while (T--) {
char str[80]; int tmp, p = 0;
for(int i = 1; i <= 4; ++i) {
str[p++] = '0'+i; str[p++] = '1';
for(int j = 2; j <= 8; ++j) {
scanf("%d", &tmp);
if(tmp == 11 || tmp == 21 || tmp == 31 || tmp == 41) {
str[p++] = '0'; str[p++] = '0';
} else {
str[p++] = '0'+(tmp/10);
str[p++] = '0'+(tmp%10);
}
}
}
str[p] = '\0';
p = 0;
for(int i = 1; i <= 4; ++i) {
for(int j = 1; j <= 7; ++j) {
Ed[p++] = i+'0'; Ed[p++] = j+'0';
}
Ed[p++] = '0'; Ed[p++] = '0';
}
Ed[p] = '\0';
bfs(str);
}
return 0;
}