您的位置:首页 > 其它

poj 1077 bfs+康托展开(8数码问题)

2014-08-05 16:06 288 查看
题意:8数码问题

思路:bfs,用康托展开来标记判重。所谓康托展开就是将1~n!个整数与n的全排列一一对应起来的一种方法,一种排列的值为i表示这种排列的字典序为第i小。

#include <stdio.h>
#include <string.h>
#define N 362880
int s[9];
int fact[9] = {40320,5040,720,120,24,6,2,1,1};
int ori[4][2] = {{0,-1},{-1,0},{0,1},{1,0}};
int flag
;
struct queue{
int s[9],dig,flag,pre;
}q
;
int end;
int contor(int s[9]){//康托展开
int i,j,res,temp;
for(i = 0,res=0;i<8;i++){
for(j = i+1,temp=0;j<9;j++)
if(s[j]<s[i])
temp++;
res += temp * fact[i];
}
return res;
}
int check(int x,int y){
if(x<0||y<0||x>2||y>2)
return 0;
return 1;
}
void print(i){
int j;
if(i!=0){
print(q[i].pre);
if(q[i].flag == 0)
putchar('l');
else if(q[i].flag == 1)
putchar('u');
else if(q[i].flag == 2)
putchar('r');
else if(q[i].flag == 3)
putchar('d');
}
}
int bfs(){
struct queue now;
int i,j,front,rear,x,y,xx,yy,temp,t[9];
front = -1;
rear = 0;
while(front < rear){
now = q[++front];
x = now.dig/3;
y = now.dig%3;
for(i = 0;i<4;i++){
xx = x+ori[i][0];
yy = y+ori[i][1];
if(check(xx,yy)){
for(j = 0;j<9;j++)
t[j] = now.s[j];
t[3*x+y] = t[3*xx+yy];
t[3*xx+yy] = 9;
temp = contor(t);
if(!flag[temp]){
flag[temp] = 1;
q[++rear].dig = 3*xx+yy;
for(j = 0;j<9;j++)
q[rear].s[j] = t[j];
q[rear].pre = front;
q[rear].flag = i;
if(temp == end){
print(rear);
return 1;
}
}
}
}
}
return 0;
}
int main(){
int i,j,k;
char ch;
freopen("a.txt","r",stdin);
memset(flag,0,sizeof(flag));
end = 0;
for(i = 0;i<9;i++){
while((ch = getchar()) && ch==' ');
if(ch == 'x'){
s[i] = 9;
q[0].dig = i;
}
else
s[i] = ch - '0';
}
i = contor(s);
flag[i] = 1;
for(i = 0;i<9;i++)
q[0].s[i] = s[i];
if(!bfs())
printf("unsolvable");
putchar('\n');
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: