Skip to content

other

原始文件为 cpp 代码,本文是转换后的 Markdown 文件。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <set>
using namespace std;

int w, h, n;

char pic[20][20]; // 输入
int num[20][20]; // 输入中的位置→图中节点的编号
int vis[200][200][200]; // 标记数组
int connect[200][200]; // 邻接表
int all; // 图中节点的数量

int que[10000000][4]; // BFS队列
int goal[4]; // 目标状态

inline void BFS() {
    // 初始化
    memset(vis, 0, sizeof(vis));
    int fro = 0, rear = 1;
    vis[que[0][1]][que[0][2]][que[0][3]] = true;

    while(fro < rear) {
        int &step = que[fro][0], &a = que[fro][1], &b = que[fro][2], &c = que[fro][3];
        if(a == goal[1] && b == goal[2] && c == goal[3]) { goal[0] = step; return; }

        for(int i = 0, t1; i <= connect[a][0]; ++i) {
            t1 = (i == 0 ? a : connect[a][i]);
            for(int j = 0, t2; j <= connect[b][0]; ++j) {
                t2 = (j == 0 ? b : connect[b][j]);
                for(int k = 0, t3; k <= connect[c][0]; ++k) {
                    t3 = (k == 0 ? c : connect[c][k]);
                    // 判断冲突-----
                    if((t1 && t2 && t1 == t2) || (t1 && t3 && t1 == t3) || (t2 && t3 && t2 == t3)) continue; // 不能重合
                    if(t1 && t2 && t1 == b && t2 == a) continue; // t1,t2不能对穿
                    if(t1 && t3 && t1 == c && t3 == a) continue; // t1,t3不能对穿
                    if(t2 && t3 && t2 == c && t3 == b) continue; // t2,t3不能对穿
                    // ----------
                    if(!vis[t1][t2][t3]) {
                        vis[t1][t2][t3] = 1;
                        que[rear][0] = step + 1, que[rear][1] = t1, que[rear][2] = t2, que[rear][3] = t3;
                        ++rear;
                    }
                }
            }
        }

        ++fro;
    }
}

int main() {
    int _t = 0;
    while(scanf("%d%d%d", &w, &h, &n) && w && h && n) {

    // 读取输入-----
        fgets(pic[0]);
        for(int i = 0; i != h; ++i) fgets(pic[i]);
    // ----------

    // 根据输入建立图-----
        // 初始化
        memset(connect, 0, sizeof(connect));
        all = 0;
        // 获得编号
        for(int i = 0; i != h; ++i) for(int j = 0; j != w; ++j) {
            if(pic[i][j] != '#') num[i][j] = ++all;
            else num[i][j] = 0;
        }
        // 建立图
        for(int i = 0; i != h; ++i) for(int j = 0; j != w; ++j) if(num[i][j]) {
            int &pos = num[i][j];
            if(num[i + 1][j]) connect[pos][++connect[pos][0]] = num[i + 1][j];
            if(num[i - 1][j]) connect[pos][++connect[pos][0]] = num[i - 1][j];
            if(num[i][j + 1]) connect[pos][++connect[pos][0]] = num[i][j + 1];
            if(num[i][j - 1]) connect[pos][++connect[pos][0]] = num[i][j - 1];
        }
    // ----------

    // 寻找初始状态和目标状态(测了一下字母范围只在abc之间所以偷懒就这么写了)
        //初始化
        que[0][0] = que[0][1] = que[0][2] = que[0][3] = 0;
        goal[0] = goal[1] = goal[2] = goal[3] = 0;
        // 寻找初始状态
        for(int i = 0; i != h; ++i) for(int j = 0; j != w; ++j) if(islower(pic[i][j])) {
            if(pic[i][j] == 'a') que[0][1] = num[i][j];
            if(pic[i][j] == 'b') que[0][2] = num[i][j];
            if(pic[i][j] == 'c') que[0][3] = num[i][j];
        }
        // 寻找目标状态
        for(int i = 0; i != h; ++i) for(int j = 0; j != w; ++j) if(isupper(pic[i][j])) {
            if(pic[i][j] == 'A') goal[1] = num[i][j];
            if(pic[i][j] == 'B') goal[2] = num[i][j];
            if(pic[i][j] == 'C') goal[3] = num[i][j];
        }
    // ----------

        BFS();

        printf("%d\n", goal[0]);
    }
}