• 九宫重排_康拓展开_bfs


      历届试题 九宫重排  
    时间限制:1.0s   内存限制:256.0MB
          
    问题描述
      如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

      我们把第一个图的局面记为:12345678.
      把第二个图的局面记为:123.46758
      显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
      本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。
    输入格式
      输入第一行包含九宫的初态,第二行包含九宫的终态。
    输出格式
      输出最少的步数,如果不存在方案,则输出-1。
    样例输入
    12345678.
    123.46758
    样例输出
    3
    样例输入
    13524678.
    46758123.
    样例输出
    22
     
     
    拿到这个题的时候没什么思路,之前也做过bfs的题,最大的问题在于状态的保存,后来看到有个编码题用到了康拓展开,豁然开朗,数学真的是奇妙啊!还有很多不知道的东西呢!
    又知道了java的几个坑,哪怕是数组直接赋值也是赋的地址,添加到链表之类的也是地址,想要不受干扰只能手工拷贝。
     
      1 package study_code;
      2 
      3 import java.util.LinkedList;
      4 import java.util.Queue;
      5 import java.util.Scanner;
      6 
      7 public class 八数码 {
      8     
      9     static int[] vis = new int [900900]; //判断哈希值是否被访问
     10     static int[] f = new int[9];    //保存阶乘
     11     static int end; //最终状态的哈希值
     12     static node start = new node(); 
     13     static String resPath;
     14     static int[][] dir = {{-1,0},{1,0},{0,-1},{0,1}};
     15     static char[] dirc = {'U','D','L','R'};
     16     static class node{
     17         int loc; //记录当前空格位置 用一个数字记录 1-9
     18         int s[]; //记录当前所有数字的位置
     19         int hashVal; //当前状态的哈希值
     20         String path = ""; //记录当前路径
     21         public node() {
     22         }
     23     }
     24     
     25     public static void fac() {
     26         f[0] = 1;
     27         for (int i = 1; i < f.length; i++) {
     28             f[i] = f[i-1] * i;
     29         }
     30     }
     31     
     32     //康拓展开
     33     public static int getHash(int[] s) {
     34         int res = 0;
     35         for (int i = 0; i < s.length; i++) {
     36             int index =0;
     37             for (int j = i+1; j < s.length; j++) {
     38                 if (s[j]<s[i]) {
     39                     index++;
     40                 }
     41             }
     42             res += index*f[9-1-i];
     43         }
     44         return res;        
     45     }
     46     
     47     
     48     public static boolean bfs() {
     49         Queue<node> q = new LinkedList<node>();
     50         q.offer(start);
     51         vis[start.hashVal] = 1;
     52         while (!q.isEmpty()) {
     53             node cur = q.poll();
     54             vis[cur.hashVal] = 1;
     55             if (cur.hashVal == end) {
     56                 resPath = cur.path;
     57                 return true;
     58             }
     59             int x =cur.loc/3;
     60             int y =cur.loc%3;
     61             for (int i = 0; i < 4; i++) {
     62                 int tx = x + dir[i][0];
     63                 int ty = y + dir[i][1];
     64                 if (tx<0||ty<0||tx>=3||ty>=3) {
     65                     continue;
     66                 }
     67                 node temp = new node();
     68                 temp.loc = tx*3+ty;
     69                 temp.path = cur.path+dirc[i];
     70                 temp.s = cur.s.clone();
     71                 //交换空格的位置
     72                 temp.s[cur.loc] = temp.s[temp.loc];
     73                 temp.s[temp.loc] = 0;
     74                 
     75                 temp.hashVal = getHash(temp.s);
     76                 if (vis[temp.hashVal] == 1) {
     77                     continue;
     78                 }
     79                 q.offer(temp);
     80                 vis[temp.hashVal] = 1;
     81             }
     82         }
     83         return false;
     84         
     85         
     86         
     87     }
     88     public static void main(String[] args) {
     89         Scanner sc = new Scanner(System.in);
     90         fac();
     91         String t = sc.nextLine();
     92         char[] c = t.toCharArray();
     93         int[] n = new int[c.length];
     94         for (int i = 0; i < c.length; i++) {
     95             if (c[i] == '.') {
     96                 n[i] = 0;
     97                 start.loc = i;
     98             }else {
     99                 n[i] = c[i] - '0';
    100             }
    101         }
    102         start.s = n.clone();
    103         start.hashVal = getHash(start.s);
    104         t = sc.nextLine();
    105         c = t.toCharArray();
    106         n = new int[c.length];
    107         for (int i = 0; i < c.length; i++) {
    108             if (c[i] == '.') {
    109                 n[i] = 0;
    110             }else {
    111                 n[i] = c[i] - '0';
    112             }
    113         }
    114         end = getHash(n);
    115         bfs();
    116         System.out.println(resPath.length());
    117     }
    118 }
  • 相关阅读:
    $Poj2228$/洛谷$SP283 Naptime$ 环形$DP$
    $Poj1952 $洛谷$1687 Buy Low,Buy Lower$ 线性$DP+$方案计数
    $Poj3585 Accumulation Degree$ 树形$DP/$二次扫描与换根法
    洛谷$1541$ 乌龟棋 线性$DP$
    $Loj10157$ 皇宫看守 树形$DP$
    $loj10156/$洛谷$2016$ 战略游戏 树形$DP$
    $Loj10155$ 数字转换(求树的最长链) 树形$DP$
    洛谷$2015$二叉苹果树
    $CH5302$ 金字塔 区间$DP$/计数类$DP$
    [hiho1035] 自驾旅行III
  • 原文地址:https://www.cnblogs.com/16crow/p/6641639.html
Copyright © 2020-2023  润新知