Skip to content

test

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

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <set>

using namespace std;

struct Point
{
    int x, y;
    void setv(int a, int b) { x = a; y = b; }
};
struct State
{
    Point p[3];
    void init() { p[1].setv(1,0); p[2].setv(0,1); }
    void init(Point a, Point b, Point c) {p[0]=a; p[1]=b; p[2]=c;}
    void setv(int idx, int a, int b) { p[idx].setv(a,b); }
};

const int maxstate = 8000000;
State st[maxstate], goal;
char save[17][17];
set<int> vis;

int w, h, ghost_num;
char dict[26];
int dis[maxstate];

bool init()
{
    scanf("%d%d%d", &w, &h, &ghost_num); ghost_num = 0; 
    st[1].init(); goal.init();
    memset(dis, 0, sizeof(dis));
    memset(dict, 0, sizeof(dict));
    memset(save, 0, sizeof(save));

    vis.clear();
    return (w && h);
}
void input();
int bfs();

int main()
{
//     freopen("in.txt", "r", stdin);
    while(true)
    {
        if(!init()) break;
        input();
        int ans = bfs();
        printf("%d\n", dis[ans]);
    }
}

int query(int ch_int)
{
    if(!dict[ch_int])
    {
        ++ghost_num;
        dict[ch_int] = ghost_num;
        return (ghost_num - 1);
    }
    return dict[ch_int] - 1;
}

void input()
{
    char line;
    for(int i = 1; i <= h; ++i) 
    {
        scanf("%c", &line);
        for(int j = 1; j <= w; ++j) 
        {
            scanf("%c", &save[i][j]);
            char ch = save[i][j];

            if(ch >= 'a' && ch <= 'z') 
            {
                int now_idx = query(ch - 'a');
                st[1].setv(now_idx, i, j);
            }else if(ch >= 'A' && ch <= 'Z') 
            {
                int now_idx = query(ch - 'A');
                goal.setv(now_idx, i, j);
            }
        }
    }
}

const int dx[] = { 0, -1, 0, 1, 0};
const int dy[] = { 0, 0, 1, 0, -1};

bool islegal(Point p, int index)
{
    if(save[p.x][p.y] == '#') return false;
    if(ghost_num < index)
    {
        int x = p.x; int y = p.y;
        return (x > 0 && y > 0 && x <= h && y <= w);
    }
    return true;
}

bool isequal(Point a, Point b)
{
    return (a.x == b.x) && (a.y == b.y);
}

bool isequal(State a, State b)
{
    for(int i = 0; i < 3; ++i)
    {
        if(!isequal(a.p[i], b.p[i])) return false;
    }
    return true;
}

bool try_to_insert(int rear)
{
    int v = 0;
    for(int i = 0; i < 3; ++i)
    {
        Point now = st[rear].p[i];
        v = (v << 5) + now.x;
        v = (v << 5) + now.y;
    }
    if(vis.count(v)) return false;

    vis.insert(v); return true;
}

int bfs()
{
    int front = 1, rear = 2; 

    int y_size = (ghost_num == 1) ? 1 : 5;
    int z_size = (ghost_num < 3) ? 1 : 5;

    while(front < rear) {
        State& s = st[front];
        if(isequal(s, goal)) return front;

        for(int x = 0; x < 5; ++x) 
        {
            Point newa{s.p[0].x+dx[x], s.p[0].y+dy[x]};
            if(!islegal(newa, 0)) continue;
            for(int y = 0; y < y_size; ++y) 
            {
                Point newb{s.p[1].x+dx[y], s.p[1].y+dy[y]};
                if(!islegal(newb, 1)) continue;
                for(int z = 0; z < z_size; ++z) 
                {
                    Point newc{s.p[2].x+dx[z], s.p[2].y+dy[z]};
                    if(!islegal(newc, 2)) continue;

                    if(!x && !y && !z) continue;
                    if(isequal(newa, newb)) continue;
                    if(isequal(newc, newb)) continue;
                    if(isequal(newc, newa)) continue;

                    if(isequal(newa, s.p[1]) && isequal(newb, s.p[0])) continue;
                    if(isequal(newa, s.p[2]) && isequal(newc, s.p[0])) continue;
                    if(isequal(newb, s.p[2]) && isequal(newc, s.p[1])) continue;

                    State& r = st[rear];
                    r.init(newa, newb, newc);

                    dis[rear] = dis[front] + 1;
                    if(try_to_insert(rear)) 
                    {
                        ++rear;
//                         printf("-------\n");
//                         printf("x = %d, y = %d, z = %d\n", x, y, z);
//                         printf("newa = (%d, %d)\n", newa.x, newa.y);
//                         printf("newb = (%d, %d)\n", newb.x, newb.y);
//                         printf("newc = (%d, %d)\n", newc.x, newc.y);
//                         printf("rear = %d\n", rear);
//                         printf("-------\n");
                    }
                }
            }
        }
        ++front;
    }

    return 0;
}