zoukankan      html  css  js  c++  java
  • 洛谷 P1379 八数码难题 Label:判重&&bfs

    特别声明:紫书上抄来的代码,详见P198 

    题目描述

    在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

    输入输出格式

    输入格式:

    输入初试状态,一行九个数字,空格用0表示

    输出格式:

    只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

    输入输出样例

    输入样例#1:
    283104765
    
    输出样例#1:
    4

    判重一 //set

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<set>//测试 
     5 #include<algorithm>
     6 using namespace std;
     7 typedef int state[9];
     8 
     9 state st[1000005],goal={1,2,3,8,0,4,7,6,5};
    10 int dis[1000005],dx[]={-1,1,0,0},dy[]={0,0,-1,1};
    11 
    12 set<int> vis;
    13 void init_lookup_table(){vis.clear();}
    14 int try_to_insert(int s){
    15     int v=0;
    16     for(int i=0;i<9;i++)v=v*10+st[s][i];
    17     if(vis.count(v)) return 0;
    18     vis.insert(v);
    19     return 1;
    20 }
    21 
    22 int bfs(){
    23     init_lookup_table();
    24     int front=1,rear=2;
    25     while(front<rear){
    26         state& s=st[front];
    27         if(memcmp(goal,s,sizeof(s))==0)return front;
    28         
    29         int z;
    30         for(z=0;z<9;z++) if(!s[z]) break;
    31         int x=z/3,y=z%3;
    32         for(int d=0;d<4;d++){
    33             int newx=x+dx[d];
    34             int newy=y+dy[d];
    35             int newz=newx*3+newy;
    36             if(newx>=0&&newx<3&&newy>=0&&newy<3){
    37                 state& t=st[rear];
    38                 memcpy(&t,&s,sizeof(s));//Copy
    39                 t[newz]=s[z];
    40                 t[z]=s[newz];
    41                 dis[rear]=dis[front]+1;
    42                 if(try_to_insert(rear)) rear++;
    43             }
    44         }
    45         front++;
    46     }
    47     return 0;
    48 }
    49 
    50 int main(){
    51 //    freopen("01.in","r",stdin);
    52     string s;cin>>s;
    53     for(int i=0;i<=9;i++)st[1][i]=s[i]-'0';
    54     
    55     int ans=bfs();
    56     if(ans>0) printf("%d
    ",dis[ans]);
    57     else printf("-1
    ");
    58     return 0;
    59 }

    紫书上说stl很慢,但是......

    膜拜洛谷测评机

    不过这是一个好方法吧.比如状态很多但很分散就可以类比set

    判重二 //hash

    代码 

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<set>//测试 
    #include<algorithm>
    using namespace std;
    typedef int state[9];
    
    state st[1000005],goal={1,2,3,8,0,4,7,6,5};
    int dis[1000005],dx[]={-1,1,0,0},dy[]={0,0,-1,1};
    
    const int hashsize=1000003;
    int head[hashsize],next[hashsize];
    void init_lookup_table(){memset(head,0,sizeof(head));}
    int hash(state& s){
        int v=0;
        for(int i=0;i<9;i++) v=v*10+s[i];
        return v%1000003;
    }
    int try_to_insert(int s){
        int h=hash(st[s]);
        int u=head[h];
        while(u){
            if(memcmp(st[u],st[s],sizeof(st[s]))==0 )return 0;
            u=next[u];
        }
        next[s]=head[h];
        head[h]=s;
        return 1;
    }
    
    int bfs(){
        init_lookup_table();
        int front=1,rear=2;
        while(front<rear){
            state& s=st[front];
            if(memcmp(goal,s,sizeof(s))==0)return front;
            
            int z;
            for(z=0;z<9;z++) if(!s[z]) break;
            int x=z/3,y=z%3;
            for(int d=0;d<4;d++){
                int newx=x+dx[d];
                int newy=y+dy[d];
                int newz=newx*3+newy;
                if(newx>=0&&newx<3&&newy>=0&&newy<3){
                    state& t=st[rear];
                    memcpy(&t,&s,sizeof(s));//Copy
                    t[newz]=s[z];
                    t[z]=s[newz];
                    dis[rear]=dis[front]+1;
                    if(try_to_insert(rear)) rear++;
                }
            }
            front++;
        }
        return 0;
    }
    
    int main(){
    //    freopen("01.in","r",stdin);
        string s;cin>>s;
        for(int i=0;i<=9;i++)st[1][i]=s[i]-'0';
        
        int ans=bfs();
        if(ans>0) printf("%d
    ",dis[ans]);
        else printf("-1
    ");
        return 0;
    }

    震惊!!!

     判重三 //编码(只适用于码数很小的情况下,比如30!就不行)

    代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<set>//测试 
     5 #include<algorithm>
     6 using namespace std;
     7 typedef int state[9];
     8 
     9 state st[1000005],goal={1,2,3,8,0,4,7,6,5};
    10 int dis[1000005],dx[]={-1,1,0,0},dy[]={0,0,-1,1};
    11 
    12 int vis[362880],fact[9];
    13 void init_lookup_table(){
    14     fact[0]=1;
    15     for(int i=1;i<9;i++) fact[i]=fact[i-1]*i;
    16 }
    17 int try_to_insert(int s){
    18     int code=0;//把st[s]映射到整数code
    19     for(int i=0;i<9;i++){
    20         int cnt=0;
    21         for(int j=i+1;j<9;j++)if(st[s][j]<st[s][i]) cnt++;
    22         code+=fact[8-i]*cnt;
    23     }
    24     if(vis[code])return 0;
    25     return vis[code]=1;
    26 }
    27 
    28 int bfs(){
    29     init_lookup_table();
    30     int front=1,rear=2;
    31     while(front<rear){
    32         state& s=st[front];
    33         if(memcmp(goal,s,sizeof(s))==0)return front;
    34         
    35         int z;
    36         for(z=0;z<9;z++) if(!s[z]) break;
    37         int x=z/3,y=z%3;
    38         for(int d=0;d<4;d++){
    39             int newx=x+dx[d];
    40             int newy=y+dy[d];
    41             int newz=newx*3+newy;
    42             if(newx>=0&&newx<3&&newy>=0&&newy<3){
    43                 state& t=st[rear];
    44                 memcpy(&t,&s,sizeof(s));//Copy
    45                 t[newz]=s[z];
    46                 t[z]=s[newz];
    47                 dis[rear]=dis[front]+1;
    48                 if(try_to_insert(rear)) rear++;
    49             }
    50         }
    51         front++;
    52     }
    53     return 0;
    54 }
    55 
    56 int main(){
    57 //    freopen("01.in","r",stdin);
    58     string s;cin>>s;
    59     for(int i=0;i<=9;i++)st[1][i]=s[i]-'0';
    60     
    61     int ans=bfs();
    62     if(ans>0) printf("%d
    ",dis[ans]);
    63     else printf("-1
    ");
    64     return 0;
    65 }

    总结起来就是:效率 hash>编码>set

    另外这里有一个详细的转载:http://blog.csdn.net/ouxijv/article/details/7203027

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 相关阅读:
    【JavaP6大纲】SpringCould篇:什么是微服务
    【JavaP6大纲】SpringCould篇: Spring Boot 和 Spring Cloud,谈谈你对它们的理解?
    【JavaP6大纲】分布式会话篇:集群部署时的分布式 Session 如何实现?
    【JavaP6大纲】SpringCould篇:Spring Cloud 和 Dubbo 有哪些区别?
    【JavaP6大纲】SpringCould篇:服务发现组件 Eureka 的主要调用过程?Eureka 和 Zookeeper 都可以提供服务注册与发现的功能,它们有什么区别?
    【JavaP6大纲】SpringCould篇:熔断框架如何做技术选型?选用 Sentinel 还是 Hystrix?
    【JavaP6大纲】SpringCould篇:如何限流?在工作中是怎么做的?说一下具体的实现?
    【JavaP6大纲】SpringCould篇:常用组件底层实现
    【JavaP6大纲】MySQL篇:SQL的整个解析、执行过程原理、SQL行转列?
    如何将百度搜索嵌入到站点中!
  • 原文地址:https://www.cnblogs.com/radiumlrb/p/5902730.html
Copyright © 2011-2022 走看看