Natsu_iiiiro

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

http://acm.hdu.edu.cn/showproblem.php?pid=1043

由于HDU这里的涉及多组数据,而每组数据按照一般的bfs()做法,即遍历每一种可行方案都保存一次路径,直到找到解就停下来,需要100+ms,这种做法放在多组数据中可能会超时,因此,不如我们只花100+ms来只做一次遍历,预先把所有能到达的状态找到并把路径记录下来,存放到char path[ ][ ]中,然后来一组数据就直接判断是否有这样的状态再进行输出(前面的也就是打表啦Σ(っ °Д °;)っ),大体上和一般的bfs()做法一样,可以使用队列,也可以使用循环自己模拟,主要问题是需要保存的状态是一个3 x 3 的矩阵,如果想要对每一种不同的序列都进行标记去重的话,选择康托展开那样的会很方便,就是说,通过某种线性变换运算(口糊),将这个 矩 阵 唯一的变成一个 对应的 实数,然后只用一维数组 (bool vis[ ])就可以进行状态标记了,嗯。具体康托展开什么的网上的讲解也有很多,本质是十进制转换为八进制,下面是在HDU上的ac代码:

#include <stdio.h>
#include <math.h>
#include <queue>
#include <string.h>
using namespace std;

int arr[3][3];
int vis[400000];
char path[400000][40];
int lev[] = {1,1,2,6,24,120,720,5040,40320,362880};
int dx[] = {-1,1,0,0};
int dy[] = {0,0,-1,1};
char dir[] = "durl";
int len;
struct node{
int s[9];
int loc;
int state;
int fa;
char d;
}n[400000];

int Inverse_cantor(int s[9])
{
int sum = 0;
for(int i = 0;i<9;i++)
{
int num = 0;
for(int j = i + 1;j<9;j++)
if(s[j] < s[i])
num++;
sum += num*lev[9 - i -1];

}
return sum + 1;
}

void find_path(node end)
{
int state = end.state;
int f = end.fa;
len = 0;
path[state][len++] = end.d;
while(f)
{
path[state][len++] = n[f].d;
f = n[f].fa;
}
}

void bfs(){
memset(vis, 0,sizeof vis);
node nex;
int head = 0,tail = 0;
for(int i = 0;i<8;i++)
n[0].s[i] = i+1;
n[0].s[8] = 0;
n[0].loc = 8;
n[0].state = 46234;
vis[46234] = 1;
while(head<=tail)
{
int x = n[head].loc / 3;
int y = n[head].loc % 3;
for(int i = 0;i<4;i++)
{
int tx = x + dx[i];
int ty = y + dy[i];
if(tx < 0 || tx>2||ty<0||ty>2) continue;

nex = n[head];
nex.loc = tx*3 + ty;
nex.s[n[head].loc] = nex.s[nex.loc];
nex.s[nex.loc] = 0;
nex.fa = head;
nex.d = dir[i];
nex.state = Inverse_cantor(nex.s);
if(!vis[nex.state])
{
vis[nex.state] = 1;
find_path(nex);
n[++tail] = nex;
}
}
head++;
}
}

int main()
{
bfs();
char ch[3];
node cur;
while(~scanf("%s",ch))
{
if(!strcmp(ch,"x"))
{
cur.s[0] = 0,cur.loc = 0;
}
else
{
cur.s[0] = ch[0] - '0';
}

for(int i = 1;i<9;i++)
{
scanf("%s",ch);
if(!strcmp(ch,"x"))
{
cur.s[i] = 0,cur.loc = i;
}
else
{
cur.s[i] = ch[0] - '0';
}
}
cur.state = Inverse_cantor(cur.s);
if(vis[cur.state])
printf("%s\n",path[cur.state]);
else
printf("unsolvable\n");
}
return 0;
}

 

posted on 2019-03-31 12:48  Natsu_iiiiro  阅读(117)  评论(0编辑  收藏  举报