您的位置:首页 > 其它

POJ 1077(HDU 1043) Eight(八数码A*算法)

2016-08-24 08:12 549 查看
通过演算发现每次一动,逆序对增加一定是偶数对,如果出现奇数则肯定不符合要求,所以要事先判断否则会超时。奇偶剪枝是一种非常常用的剪枝方法,如果在搜索中超时,可以尝试奇偶剪枝。

八数码问题中是0~8的9个数字,如果当做排列是不能算0的,相当于1~8的8位数字的排列,当左右移动时,1~8的排列,没有改变,当上下移动时,上下的数字走到0的位置都要经过2次的交换,所以交换是偶数次的,那么不改变排列的奇偶性,1~8的标准排列逆序对是0,那么标准排列是偶排列,如果八数码排列是奇排列,那么直接剪枝。

//
//  main.cpp
//  Richard
//
//  Created by 邵金杰 on 16/8/24.
//  Copyright © 2016年 邵金杰. All rights reserved.
//

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=400000;
struct node{
int sta[9];
int f,g,h;
int pos;
int hash;
bool operator < (const node &e) const {
return f>e.f;
}
};
int vis[maxn];
int End[9]={1,2,3,4,5,6,7,8,0};
int ha[9]={1,1,2,6,24,120,720,5040,40320};
struct pre{
int pre;
char ch;
}pr[maxn];
int get_hash(int a[9])
{
int res=0;
for(int i=0;i<9;i++)
{
int k=0;
for(int j=i+1;j<9;j++)
{
if(a[j]<a[i]) k++;
}
res+=k*ha[8-i];
}
return res;
}
int get_h(int a[9])
{
int dist=0;
for(int i=0;i<9;i++)
{
int x1=i/3,y1=i%3;
int x2,y2;
for(int j=0;j<9;j++)
{
if(End[j]==a[i]) {x2=j/3;y2=j%3;break;}
}
dist+=(x1-x2>0?x1-x2:-(x1-x2));
dist+=(y1-y2>0?y1-y1:-(y1-y2));
}
return dist;
}
bool reverse(node s)
{
int times=0;
for(int i=0;i<9;i++)
{
if(s.sta[i]==0) continue;
for(int j=i+1;j<9;j++)
{
if(s.sta[j]==0) continue;
if(s.sta[i]>s.sta[j]) times++;
}
}
return times&1;
}
bool inside(int x,int y)
{
if(x>=0&&x<=2&&y>=0&&y<=2) return true;
return false;
}
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
char d[5]="lurd";
void swap(int *a,int pos1,int pos2)
{
int temp=a[pos1];
a[pos1]=a[pos2];
a[pos2]=temp;
}
void print(int x)
{
if(pr[x].pre==-1) return ;
print(pr[x].pre);
printf("%c",pr[x].ch);
}
void Astar(node s)
{
int end_hash=get_hash(End);
if(end_hash==s.hash) {printf("\n");return ;}
memset(vis,0,sizeof(vis));
vis[s.hash]=1;
pr[s.hash].pre=-1;
priority_queue<node> pq;
pq.push(s);
node p,q;
while(!pq.empty())
{
p=pq.top();
pq.pop();
int x=p.pos/3,y=p.pos%3;
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(!inside(nx,ny)) continue;
q=p;
swap(q.sta,x*3+y,nx*3+ny);
q.hash=get_hash(q.sta);
if(vis[q.hash]) continue;
vis[q.hash]=1;
q.pos=nx*3+ny;
q.g++;
q.h=get_h(q.sta);
q.f=q.g+q.h;
pr[q.hash].pre=p.hash;
pr[q.hash].ch=d[i];
if(q.hash==end_hash) {print(end_hash);printf("\n");return ;}
pq.push(q);
}
}
}
int main()
{
char str[100];
while(gets(str))
{
int len=(int)strlen(str);
node s;
int k=0;
int flag=0;
for(int i=0;i<len;i++)
{
if(str[i]==' ') continue;
if(str[i]=='x') {flag=k;s.sta[k++]=0;}
else s.sta[k++]=str[i]-'0';
}
if(reverse(s))
{
printf("unsolvable\n");
continue;
}
s.g=0;
s.h=get_h(s.sta);
s.f=s.g+s.h;
s.hash=get_hash(s.sta);
s.pos=flag;
Astar(s);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: