2024年3月27号题解

Open the Lock

解题思路

  1. 很明显从起点到终点的距离等于终点到起点的距离,那么它就是一个无向图
  2. 那么我们可以使用dbfs来进行剪枝,来优化我们的搜索

代码实现

#define  _CRT_SECURE_NO_WARNINGS
#include <sstream>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>
#include<queue>
#include <set>
#define sc scanf
#define pr printf

using namespace std;

const int M = 10000;//最多10000种状态

int t;//样例个数
int q1[M];//从起点遍历的队列
int q2[M];//从终点遍历的队列
int l1;//q1的队列头
int l2;//q2的队列头
int r1;//q1的队列尾
int r2;//q2的队列尾
bool v1[M];//起点出发访问过的状态
bool v2[M];//从终点出发访问过的状态
int a[4];//用来存放状态
int b[4];//暂时存放状态

int getStatus(int a[]) {//给定一个数组返回它对应的状态
        int ans = a[0] * 1000 + a[1] * 100 + a[2] * 10 + a[3];

        return ans;
} 

void dbfs()//双向bfs
{
        int s1 = 0;//起点状态
        int s2 = 0;//终点状态
        int level1 = 0;//从起点出发的层数
        int level2 = 0;//从终点出发的层数

        memset(v1, 0, sizeof(v1));//给v1数组清0
        memset(v2, 0, sizeof(v2));//给v2数组清0
        r2 = r1 = l2 = l1 = 0;

        sc("%d", &s1);//读入起点的状态
        sc("%d", &s2);//读入终点的状态

        v1[s1] = 1;//标记起点状态已访问
        v2[s2] = 1;//标记终点状态已访问
        q1[r1++] = s1;//把起点加入起点队列
        q2[r2++] = s2;//把终点加入终点队列
                
        while (l1 < r1 && l2 < r2) {//只要两个队列没有空
                int size1 = r1 - l1;//计算起点队列中的元素个数
                int size2 = r2 - l2;//计算终点队列种的元素个数

                if (size1 <= size2) {//如果起点队列中的元素个数更少
                        for (int i = 0; i < size1; i++) {//遍历起点队列
                                s1 = q1[l1++];//出队
                                       
                                if (v2[s1]) {//如果在终点队列中访问过的状态出现过,代表这条路径可以从终点到起点
                                        pr("%d\n", level1 + level2);
                                        return;//第一次就是最短路径
                                }

                                //取出对应的状态
                                b[0] = a[0] = s1 / 1000;
                                b[1] = a[1] = s1 / 100 % 10;
                                b[2] = a[2] = s1 / 10 % 10;
                                b[3] = a[3] = s1 % 10;
                                //+1
                                for (int j = 0; j < 4; j++) {
                                        if (b[j] == 9) {
                                                b[j] = 1;
                                                int t = getStatus(b);
                                                if (!v1[t]) {
                                                        v1[t] = 1;
                                                        q1[r1++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                        else {
                                                b[j] += 1;
                                                int t = getStatus(b);
                                                if (!v1[t]) {
                                                        v1[t] = 1;
                                                        q1[r1++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                }

                                // -1
                                for (int j = 0; j < 4; j++) {
                                        if (b[j] == 1) {
                                                b[j] = 9;
                                                int t = getStatus(b);
                                                if (!v1[t]) {
                                                        v1[t] = 1;
                                                        q1[r1++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                        else {
                                                b[j] -= 1;
                                                int t = getStatus(b);
                                                if (!v1[t]) {
                                                        v1[t] = 1;
                                                        q1[r1++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                }
                                //swap
                                for (int j = 0; j < 3; j++) {
                                        swap(b[j], b[j + 1]);
                                        int t = getStatus(b);

                                        if (!v1[t]) {
                                                v1[t] = 1;
                                                q1[r1++] = t;
                                        }
                                        swap(b[j], b[j + 1]);
                                }
                        }
                        level1++;//层数加一
                }
                else {
                        for (int i = 0; i < size2; i++) {//遍历终点队列
                                s1 = q2[l2++];//出队

                                if (v1[s1]) {//如果终点访问过的状态起点访问过了,那么这条路就是最短路满足要求
                                        pr("%d\n", level1 + level2);
                                        return;
                                }
                                //取出对应的状态
                                b[0] = a[0] = s1 / 1000;
                                b[1] = a[1] = s1 / 100 % 10;
                                b[2] = a[2] = s1 / 10 % 10;
                                b[3] = a[3] = s1 % 10;
                                //+1
                                for (int j = 0; j < 4; j++) {
                                        if (b[j] == 9) {
                                                b[j] = 1;
                                                int t = getStatus(b);
                                                if (!v2[t]) {
                                                        v2[t] = 1;
                                                        q2[r2++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                        else {
                                                b[j] += 1;
                                                int t = getStatus(b);
                                                if (!v2[t]) {
                                                        v2[t] = 1;
                                                        q2[r2++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                }

                                // -1
                                for (int j = 0; j < 4; j++) {
                                        if (b[j] == 1) {
                                                b[j] = 9;
                                                int t = getStatus(b);
                                                if (!v2[t]) {
                                                        v2[t] = 1;
                                                        q2[r2++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                        else {
                                                b[j] -= 1;
                                                int t = getStatus(b);
                                                if (!v2[t]) {
                                                        v2[t] = 1;
                                                        q2[r2++] = t;
                                                }
                                                b[j] = a[j];
                                        }
                                }
                                //swap相邻元素
                                for (int j = 0; j < 3; j++) {
                                        swap(b[j], b[j + 1]);//交换
                                        int t = getStatus(b);

                                        if (!v2[t]) {
                                                v2[t] = 1;
                                                q2[r2++] = t;
                                        }
                                        swap(b[j], b[j + 1]);//再交换回来,就恢复原装了
                                }
                        }
                        level2++;//层数加一
                }
        }
}

int main() {
        sc("%d", &t);

        while (t--) {
                dbfs();
        }

        return 0;
} 

 

posted @ 2024-03-27 23:59  lwj1239  阅读(2)  评论(0编辑  收藏  举报