zoukankan      html  css  js  c++  java
  • 洛谷P1379-八数码难题

    Problem 洛谷P1379-八数码难题

    Accept: 2.9k    Submit: 8.3k
    Time Limit: 1000 mSec    Memory Limit : 128MB

    Problem Description

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

     Input

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

     Output

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

     

     Sample Input

    283104765
     

     Sample Output

    4
     
     
    题目链接:https://www.luogu.org/problemnew/show/P1379
     
    题解:经典的八数码问题,其实还是比较简单的,两个需要注意的地方,一是判重,二是双向BFS。
    判重,由于是0~8的排列,因此用康托展开来判重是很好的选择,不用处理冲突。
    双向BFS无论是在空间上还是在时间上都比BFS优化了不少,操作也很容易,基本就是把bool型的vis数组变成int型,不同状态扩展来的做不同标记即可。
     
     
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <queue>
     6 #include <algorithm>
     7 using namespace std;
     8 
     9 const int maxn = 400000;
    10 int Fac[10] = {1,2,6,24,120,720,5040,40320,362880};
    11 int vis[maxn],dis[maxn];
    12 
    13 int Cantor(int num[10]){
    14     int ans = 0;
    15     for(int i = 0;i < 9;i++){
    16         int cnt = 0;
    17         for(int j = i+1;j < 9;j++){
    18             if(num[j] < num[i]) cnt++;
    19         }
    20         ans += Fac[7-i]*cnt;
    21     }
    22     ans++;
    23     return ans;
    24 }
    25 
    26 struct Point{
    27     int pai[10];
    28     int sit,flag,pos;
    29     Point() {}
    30     Point(int sit = 0,int flag = 0,int pos = 0) :
    31         sit(sit),flag(flag),pos(pos) {}
    32 };
    33 
    34 int Tar[10] = {1,2,3,8,0,4,7,6,5};
    35 int Ori[10];
    36 int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
    37 int ori,tar,loc;
    38 queue<Point> que;
    39 
    40 bool Judge(int x,int y){
    41     if(0<=x && 0<=y && x<3 && y<3) return true;
    42     return false;
    43 }
    44 
    45 int DBFS(){
    46     Point first(ori,1,loc),second(tar,2,4);
    47     memcpy(first.pai,Ori,sizeof(Ori));
    48     memcpy(second.pai,Tar,sizeof(Tar));
    49     que.push(first),que.push(second);
    50     vis[ori] = 1;
    51     vis[tar] = 2;
    52     dis[ori] = dis[tar] = 0;
    53     while(!que.empty()){
    54         Point first = que.front();
    55         que.pop();
    56         int x = first.pos/3,y = first.pos%3;
    57         for(int i = 0;i < 4;i++){
    58             int xx = x+dir[i][0],yy = y+dir[i][1];
    59             if(Judge(xx,yy)){
    60                 Point temp = first;
    61                 swap(temp.pai[first.pos],temp.pai[xx*3+yy]);
    62                 int con = Cantor(temp.pai);
    63                 if(!vis[con]){
    64                     vis[con] = first.flag;
    65                     temp.pos = xx*3+yy;
    66                     temp.sit = con;
    67                     dis[con] = dis[first.sit]+1;
    68                     que.push(temp);
    69                 }
    70                 else{
    71                     if(vis[con] != first.flag){
    72                         return 1+dis[con]+dis[first.sit];
    73                     }
    74                 }
    75             }
    76         }
    77     }
    78     return -1;
    79 }
    80 
    81 int main()
    82 {
    83     //freopen("input.txt","r",stdin);
    84     for(int i = 0;i < 9;i++){
    85         scanf("%1d",&Ori[i]);
    86         if(Ori[i] == 0) loc = i;
    87     }
    88     ori = Cantor(Ori);
    89     tar = Cantor(Tar);
    90     if(ori == tar){
    91         printf("%d
    ",0);
    92         return 0;
    93     }
    94     memset(vis,0,sizeof(vis));
    95     printf("%d
    ",DBFS());
    96     return 0;
    97 }
  • 相关阅读:
    IntelliJ IDEA 偏好设置
    Unix环境下的5中IO模型
    Hbase原理、基本概念、基本架构
    可参考的技术博客
    Hadoop生态系统介绍
    oracle 添加表分区和索引分区,修改索引分区默认表空间
    koa redis 链接
    Node-APN 开源推送服务
    NodeJs 笔记
    windows防火墙无法启动,服务不存在
  • 原文地址:https://www.cnblogs.com/npugen/p/9496008.html
Copyright © 2011-2022 走看看