zoukankan      html  css  js  c++  java
  • 挑战程序设计竞赛 2章习题 AOJ 0121 Seven Puzzle bfs

    地址  https://vjudge.net/problem/Aizu-0121

    题目大意是 0~7 8个数字随机分布在两行中,我们可以上下左右交换0和它周边的数字来将8个数字组成最终形态

    如图

    最终形态

    输入格式

    一行输入0~7   8个数字  空格隔开

    输出格式

    每行输出上述数据 达到最终形态的步数

    Sample Input
    0 1 2 3 4 5 6 7
    1 0 2 3 4 5 6 7
    7 6 5 4 3 2 1 0
    Output for the Sample Input
    0
    1
    28

    解法:

    使用bfs得到最短移动步骤

    但是由于没有明确的移动目标,我们不清楚如何移动才是与最终形态接近了,所以可以逆向思考,从最终形态生成所有可能的组合和达到这个组合的步数,使用哈希记录方便查询。

    之后直接查询即可。

    进阶的资料 随着状态数目的增加比如八数码 需要考虑状态压缩。 一个状态是否可以达到最终形态,可以使用逆序对来确认,关键字是康托展开,大家可以自行查询。

    代码

    // 11235555.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include <iostream>
    #include <string>
    #include <queue>
    #include <unordered_map>
    
    using namespace std;
    
    string targetStr = "01234567";
    
    unordered_map<string, int> mm;
    
    int mv[4] = { 1,-1,4,-4 };
    
    void bfs() {
        queue<pair<string, int>> q;
        q.push({ targetStr ,0 });
    
        while (!q.empty()) {
            pair<string, int> p = q.front(); q.pop();
            string  s = p.first; int step = p.second;
            mm[s] = step;
    
            int idx = s.find('0');
            for (int i = 0; i < 2; i++) {
                int newidx = idx + mv[i];
                if (idx / 4 == newidx / 4 && newidx >=0 && newidx<8) {
                    string tmp = s;  swap(tmp[idx], tmp[newidx]);
                    if (mm.count(tmp) == 0) {
                        mm[tmp] = step + 1;
                        q.push({ tmp,step + 1 });
                    }
                }
            }
            for (int i = 2; i < 4; i++) {
                int newidx = idx + mv[i];
                if (idx / 4 != newidx / 4 && newidx >= 0 && newidx < 8) {
                    string tmp = s;  swap(tmp[idx], tmp[newidx]);
                    if (mm.count(tmp) == 0) {
                        mm[tmp] = step + 1;
                        q.push({ tmp,step + 1 });
                    }
                }
            }
        }
    
    
    
    }
    
    int main()
    {
        bfs();
        string s;
        while (getline(cin,s)) {
            string curr;
            for (auto& e : s) {
                if (e != ' ') curr += e;
            }
            cout << mm[curr] <<endl;
        }
    
        return 0;
    }
  • 相关阅读:
    单片机触摸屏校准
    C中的预编译宏定义
    Android之网络摄像头
    曾经的UCOSii
    关于ST-Link下载STM32程序的使用
    关于IAR开发STM32配置
    学习C#(一)
    ESP8266使用详解--基于Lua脚本语言
    (五)Lua脚本语言入门
    (四)Lua脚本语言入门(数组遍历)
  • 原文地址:https://www.cnblogs.com/itdef/p/14288427.html
Copyright © 2011-2022 走看看