【搜索进阶】hdu 1043 Eight

来源:互联网 发布:淘宝上的k歌麦克风 编辑:程序博客网 时间:2024/05/21 09:11
题目链接: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;}


0 0
原创粉丝点击