您的位置:首页 > 其它

【搜索进阶】hdu 1043 Eight

2014-08-28 22:27 232 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043

A*: 因为每次移动都会影响一个点的曼哈顿距离(不算x),构造h()为所有数字块的曼哈顿距离和,用逆序数hash(算x),根据逆序数奇偶性(不算x)减掉无法到达的情况;在构造优先队列时当f相同时按照g值从大到小排序,这样又是一个很给力的减枝

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct S {
char maze[3][3];
int x , y;
int g , h , f;
S() {}
S(const S& ts) {
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
maze[i][j] = ts.maze[i][j];
x = ts.x; y = ts.y;
g = ts.g; h = ts.h; f = ts.f;
}
friend bool operator < (const S& a,const S& b) {
if(a.f == b.f) return a.g < b.g;
return a.f > b.f;
}
}s;
const int fac[] = {1,1,2,6,24,120,720,5040,40320};
bool vis[363000];
int pre[363000];
char op[363000];
inline int inv_hash(S ts) {
char str[11]; int ans = 0;
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
str[i*3+j] = ts.maze[i][j];
int cnt = 0;
for(int k=i*3+j-1;k>=0;k--) {
if(str[k] > str[i*3+j]) cnt++;
}
ans += fac[i*3+j] * cnt;
}
}
return ans;
}
const int pos[][2]={{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}};
inline int abs(int x) { return x < 0 ? -x : x; }
inline int h(S ts) {
int val = 0;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++) {
if(ts.maze[i][j] == 'x') continue;
int c = ts.maze[i][j] - '1';
val += abs(pos[c][0]-i)+abs(pos[c][1]-j);
}
return val;
}
const int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
bool bfs() {
memset(vis,false,sizeof(vis));
priority_queue<S> que;
que.push(s);
while(!que.empty()) {
S u  = que.top(); que.pop();
int ihu = inv_hash(u);
for(int i=0;i<4;i++) {
S v = u;
v.x += dir[i][0];
v.y += dir[i][1];
if(v.x<0||v.y<0||v.x>=3||v.y>=3) continue;
v.maze[u.x][u.y]=u.maze[v.x][v.y];
v.maze[v.x][v.y]='x';
v.g+=1; v.h=h(v); v.f=v.g+v.h;
int ihv = inv_hash(v);
if(vis[ihv]) continue;
vis[ihv] = true;
pre[ihv] = ihu;
if(i == 0) op[ihv] = 'd';
else if(i == 1) op[ihv] = 'r';
else if(i == 2) op[ihv] = 'u';
else if(i == 3) op[ihv] = 'l';
if(ihv == 0) return true;
que.push(v);
}
}
return false;
}
inline bool inv_check() {
char str[11];
int cnt = 0;
for(int i=0;i<3;i++) {
for(int j=0;j<3;j++) {
str[i*3+j] = s.maze[i][j];
if(str[i*3+j] == 'x') continue;
for(int k=i*3+j-1;k>=0;k--) {
if(str[k]=='x') continue;
if(str[k] > str[i*3+j]) cnt++;
}
}
}
return !(cnt&1);
}
char in[111];
char stk[111];
int main() {
while(gets(in)) {
for(int i=0,x=0,y=0;in[i];i++) {
if((in[i]<='9'&&in[i]>='0')||in[i]=='x') {
s.maze[x][y] = in[i];
if(in[i]=='x') { s.x=x;s.y=y; }
y++; if(y == 3) y=0,x++;
}
}
if(!inv_check()) {
puts("unsolvable");
continue;
}
s.g=0; s.h=h(s); s.f=s.h;
int shash = inv_hash(s);
if(shash==0) { puts(""); continue; }
bfs();
int top = -1 , thash = 0;
while(thash != shash) {
stk[++top] = op[thash];
thash = pre[thash];
}
for(int i=top;i>=0;i--) {
putchar(stk[i]);
}
puts("");
}
return 0;
}


单广预处理: 从最终状态向所有状态搜索,记录前驱,然后直接输出就好

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
struct S{
char maze[3][3];
int x,y;
S(){}
S(const char *str){
for(int i=0,tx=0,ty=0;str[i];i++){
if((str[i]<='9'&&str[i]>='0')||str[i]=='x'){
maze[tx][ty]=str[i];
if(str[i]=='x'){x=tx;y=ty;}
ty++;
if(ty==3){ty=0;tx++;}
}
}
}
};
int pre[363000];
char op[363000];
const int fac[]={1,1,2,6,24,120,720,5040,40320};
bool  vis[363000];
inline int inv_hash(S ts){
char str[10]; int ans=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
str[i*3+j]=ts.maze[i][j];
int cnt=0;
for(int k=i*3+j-1;k>=0;k--){
if(str[k]>str[i*3+j]) cnt++;
}
ans+=fac[i*3+j]*cnt;
}
}
return ans;
}
S s;
const int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
const char cdir[]="dulr";
void bfs(){
memset(vis,false,sizeof(vis));
memset(pre,-1,sizeof(pre));
queue<S> que;
que.push(s);
while(!que.empty()){
S u=que.front(); que.pop();
int ihu=inv_hash(u);
for(int i=0;i<4;i++){
S v=u;
v.x+=dir[i][0];
v.y+=dir[i][1];
if(v.x<0||v.y<0||v.x>=3||v.y>=3) continue;
v.maze[u.x][u.y]=v.maze[v.x][v.y];
v.maze[v.x][v.y]='x';
int ihv=inv_hash(v);
if(vis[ihv]) continue;
vis[ihv]=true;
pre[ihv]=ihu;
op[ihv]=cdir[i];
que.push(v);
}
}
}
char in[100];
char stk[100];
int main(){
s=S("12345678x");
bfs();
while(gets(in)){
s=S(in);
int ihs=inv_hash(s);
if(pre[ihs]==-1){puts("unsolvable");continue;}
if(ihs==0){puts("");continue;}
int top=-1,tmp=ihs;
while(tmp){
putchar(op[tmp]);
tmp=pre[tmp];
}
puts("");
}
return 0;
}


IDA*函数:和A*一样的h()函数,内存占用小是其优势。

#include<cstdio>
#include<cstring>
using namespace std;
struct S{
char maze[3][3];
int x,y;
int g,h,f;
S(){}
S(const S& ts){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
maze[i][j]=ts.maze[i][j];
}
}
x=ts.x; y=ts.y;
}
void show(){
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
putchar(maze[i][j]);
}
puts("");
}
}
};
const int pos[][2]={{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}};
inline int ABS(int x){
if(x<0) return-x;
else return x;
}
inline int h(S ts){
int val=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(ts.maze[i][j]=='x') continue;
int c=ts.maze[i][j]-'1';
val+=ABS(pos[c][0]-i)+ABS(pos[c][1]-j);
}
}
return val;
}
int fac[]={1,1,2,6,24,120,720,5040,40320};
inline int inv_hash(S ts){
char str[10]; int ans=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
str[i*3+j]=ts.maze[i][j];
int cnt=0;
for(int k=i*3+j-1;k>=0;k--){
if(str[k]>str[i*3+j]) cnt++;
}
ans+=fac[i*3+j]*cnt;
}
}
return ans;
}
int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int ans[50],deep;
bool vis[363000];
S ts;
bool dfs(int d){
if(h(ts)==0) return true;
if(h(ts)+d>deep) return false;
int x=ts.x;
int y=ts.y;
for(int i=0;i<4;i++){
int tx=ts.x+dir[i][0];
int ty=ts.y+dir[i][1];
if(tx<0||ty<0||tx>=3||ty>=3) continue;
ts.maze[x][y]=ts.maze[tx][ty];
ts.maze[tx][ty]='x';
int tmp=inv_hash(ts);
if(vis[tmp]){
ts.maze[tx][ty]=ts.maze[x][y];
ts.maze[x][y]='x';
continue;
}
vis[tmp]=true;
ts.x=tx; ts.y=ty;
ans[d]=i;
if(dfs(d+1)) return true;
vis[tmp]=false;
ts.x=x; ts.y=y;
ts.maze[tx][ty]=ts.maze[x][y];
ts.maze[x][y]='x';
}
return false;
}
S s;
bool inv_check(){
char str[10];
int cnt=0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
str[i*3+j]=s.maze[i][j];
if(str[i*3+j]=='x') continue;
for(int k=i*3+j-1;k>=0;k--){
if(str[k]=='x') continue;
if(str[k]>str[i*3+j]) cnt++;
}
}
}
return!(cnt&1);
}
char in[100];
int main(){
while(gets(in)){
for(int i=0,x=0,y=0;in[i];i++){
if((in[i]<='9'&&in[i]>='0')||in[i]=='x'){
s.maze[x][y]=in[i];
if(in[i]=='x'){s.x=x;s.y=y;}
y++;
if(y==3) y=0,x++;
}
}
if(!inv_check()){ puts("unsolvable"); continue;}
memset(vis,false,sizeof(vis));
vis[inv_hash(s)]=true;
ts=s; deep=0;
while(true){
if(dfs(0)) break;
deep++;
}
for(int i=0;i<deep;i++){
if(ans[i]==0) putchar('d');
else if(ans[i]==1) putchar('r');
else if(ans[i]==2) putchar('u');
else if(ans[i]==3) putchar('l');
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: