• 九宫重排(搜索)


    1581: 题目名称:九宫重排

    时间限制: 1 Sec  内存限制: 128 MB
    提交: 2  解决: 1
    [提交] [状态] [讨论版] [命题人:外部导入]

    题目描述

    问题描述
    如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。
    我们把第一个图的局面记为:12345678.
    把第二个图的局面记为:123.46758
    显然是按从上到下,从左到右的顺序记录数字,空格记为句点。
    本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

     

    输入

    输入格式
    输入第一行包含九宫的初态,第二行包含九宫的终态。

    输出

    输出格式
    输出最少的步数,如果不存在方案,则输出-1。

    样例输入

    12345678.
    123.46758
    

    样例输出

    3
    bfs+康托展开判断是否重复操作
    #include<bits/stdc++.h>
    #include<queue>
    #include<bits/stdc++.h>
    using namespace std;
    int p[15], q[15],t[1000005][15],cnt[1000005],vis[1000005];
    int fac[15] = { 1 };
    int d[5][5] = { {1,0},{-1,0},{0,1},{0,-1} };
    int kt(int *a) {
          int sum = 0,u=0;
          for (int i = 0; i < 8; i++) {
              u = 0;
              for (int j = i + 1; j < 9; j++) {
                  if (a[i] > a[j])u++;
              }
              sum += u * fac[8 - i];
          }
          if (vis[sum])return 0;
          else {
              vis[sum] = 1;
              return 1;
          }
    }
    int bfs() {
           int head = 0, tail = 1;
           memcpy(t[0], p, sizeof(p));
           while (head < tail) {
               int tmp[15];
               memcpy(tmp, t[head], sizeof(t[head]));
               if (memcmp(tmp, q,sizeof(q)) == 0)return head;
               int k;
               for (k = 0; k < 9; k++)if (!tmp[k])break;
               int x = k / 3, y = k % 3;
               for (int i = 0; i < 4; i++) {
                   int cx = x + d[i][0], cy = y+d[i][1];
                   if (cx < 0 || cy < 0 || cx>2 || cy>2)continue;
                   int now = 3 * cx + cy;
                   int temp[15];
                   memcpy(temp, tmp, sizeof(tmp));
                   temp[k] = tmp[now];
                   temp[now] = 0;
                   if (kt(temp))memcpy(t[tail],temp,sizeof(temp)),cnt[tail++] = cnt[head]+1;
               }
               ++head;
           }
           return -1;
    }
    int main() {
        char ch;
        //for (int i = 1; i <= 10; i++)cout << fac[i] << endl;
        for (int i = 1; i <= 9; i++)fac[i] = i * fac[i - 1];
        //for (int i = 1; i <= 10; i++)cout << fac[i] << endl;
        for (int i = 0; i < 9; i++) {
            cin >> ch;
            if (ch == '.')p[i] = 0;
            else p[i] = ch - '0';
        }
        for (int i = 0; i < 9; i++) {
            cin >> ch;
            if (ch == '.')q[i] = 0;
            else q[i] = ch - '0';
        }
        int ans = bfs();
        if (ans == -1)cout << -1 << endl;
        else cout << cnt[ans] << endl;
        return 0;
    }
  • 相关阅读:
    vim常用命令集(摘自鸟哥私房菜)
    LINUX下把多行文件合并成一行,并组装成SQL
    UVA 10148 Advertisement (贪心 + 区间选点问题)
    linux环境应用程序LOG日志打印(C语言)
    SharePoint 2013 Nintex Workflow 工作流帮助(三)
    SharePoint 2013 Nintex Workflow 工作流帮助(二)
    SharePoint 2013 Nintex Workflow 工作流帮助(一)
    SharePoint表单和工作流
    SharePoint表单和工作流
    SharePoint表单和工作流
  • 原文地址:https://www.cnblogs.com/czy-power/p/10356930.html
Copyright © 2020-2023  润新知