[蓝桥杯2017初赛]跳蚱蜢

题目链接:http://oj.ecustacm.cn/problem.php?id=1318

题目描述

如图所示: 有9只盘子,排成1个圆圈。其中8只盘子内装着8只蚱蜢,有一个是空盘。

我们把这些蚱蜢顺时针编号为 1~8。每只蚱蜢都可以跳到相邻的空盘中,也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,并且保持空盘的位置不变(也就是1-8换位,2-7换位,...),至少要经过多少次跳跃? 

输出

输出一个整数表示答案

思路:

1、 可以将空盘子看成9的盘子,我们利用状态压缩的思想,把盘子刚开始的状态定义成: 123456789 , 那么最后盘子逆序后的状态就应该为 876543219 ,蚂蚱可以跳一个格子和两个格子,那么蚂蚱的跳跃距离就是|2|距离  
2、 我们可以用滚动数组的方法来使盘子可以左右移动 [(x+9)%9]
3、 然后进行广搜就可以了。

 

#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <cstdio>
#include <iomanip>
#include <time.h>

#define LL long long
#define INF 0x3f3f3f3f
#define ls nod<<1
#define rs (nod<<1)+1

const int maxn = 1e9 + 10 ;
const LL mod = 20010905;

int st = 123456789,ed = 876543219;
int dir[4] = {1,-1,-2,2};
bool vis[maxn];
int a[10];

int getnum() {
    int sum = 0;
    for (int i = 0;i < 9;i++) {
        sum *= 10;
        sum += a[i];
    }
    return sum;
}

void bfs() {
    std::queue<std::pair<int,int> > q;
    memset(vis,0, sizeof(vis));
    q.push(std::make_pair(st,0));
    while (!q.empty()) {
        int x = q.front().first;
        int step = q.front().second;
        q.pop();
        if (vis[x])
            continue;
        vis[x] = true;
        if (x == ed) {
            printf("%d
",step);
            return ;
        }
        int j = 8,now;
        while (x) {
            if (x % 10 == 9)
                now = j;
            a[j--] = x % 10;
            x /= 10;
        }
        for (int i = 0;i < 4;i++) {
            std::swap(a[now],a[(now+dir[i]+9)%9]);
            int val = getnum();
            if (!vis[val]) {
                q.push(std::make_pair(val,step+1));
            }
            std::swap(a[now],a[(now+dir[i]+9)%9]);
        }
    }
}

int main() {
    bfs();
    return 0;
}
原文地址:https://www.cnblogs.com/-Ackerman/p/12245137.html