제출 #1361233

#제출 시각아이디문제언어결과실행 시간메모리
1361233jbn8로봇 (APIO13_robots)C++20
100 / 100
721 ms69592 KiB
#include <ios>
#include <iostream>
#include <queue>
#include <vector>
#include <cassert>
using namespace std;

// 0
//1 3
// 2
struct position{
    int x,y;
    explicit operator bool(){
        return x != -1;
    }
    position forward(int dir){
        return position{x+(dir&1)*(dir-2), y+(!(dir&1))*(dir-1)};
    }
    bool operator==(const position& b) const{
        return x == b.x && y == b.y;
    }
    void _print(){
        cout << y << ' ' << x;
    }
    void print(){
        cout << y << ' ' << x << '\n';
    }
};

class Board{
public:
    vector<vector<int>> types;
    vector<vector<vector<position>>> jumps;
    int w, h;
    vector<position> bots;
    int nbBots;
    Board(){}
    Board(int _w, int _h, int _nbBots):
        w(_w),
        h(_h),
        types(_h, vector<int>(_w)),
        jumps(_h, vector<vector<position>>(_w, vector<position>(4, {-1, -1}))),
        nbBots(_nbBots),
        bots(_nbBots){}
    void read(){
        for(int y=0; y<h; y++){
            string line;
            getline(cin, line);
            while(!line.size())getline(cin, line);
            for(int x=0; x<w; x++){
                if(isupper(line[x]))
                    types[y][x] = (line[x] == 'C')+1;
                else if(isalpha(line[x]))
                    types[y][x] = 3;
                else if(isdigit(line[x]))
                    bots[line[x]-'1'] = {x, y};
            }
        }
    }
    int changedir(position pos, int dir){
        if(types[pos.y][pos.x] == 1)
            return (dir+1)&3;
        else if(types[pos.y][pos.x] == 2)
            return (dir-1)&3;
        return dir;
    }
    bool isvalid(position pos){
        return 
            pos.x >= 0 && pos.x < w &&
            pos.y >= 0 && pos.y < h &&
            types[pos.y][pos.x] != 3;
    }
    position jump(position cur, int dir){
        if((bool)jumps[cur.y][cur.x][dir]){
            return jumps[cur.y][cur.x][dir];
        }
        position start = cur;
        int startdir = dir;
        vector<pair<position, int>> stack;
        stack.push_back({cur, dir});
        while(isvalid(cur.forward(dir))){
            cur = cur.forward(dir);
            dir = changedir(cur, dir);
            stack.push_back({cur, dir});
        }
        assert(isvalid(cur));
        for(auto state:stack){
            jumps[state.first.y][state.first.x][state.second] = cur;
        }
        //start._print();cout <<  '(' << startdir << ") -> ";
        //cur.print();
        return cur;
    }
};
int n, w, h;
int MAX;
Board board;
//[sizerange][startrange][y][x]
vector<vector<vector<vector<int>>>> fromStart;

vector<pair<position, int>> Q;
void bfs(position pos, int id){
    int start = 0;
    int end = 0;
    Q[end++] = {pos, 0};
    fromStart[0][id][pos.y][pos.x] = 0;
    while(start < end){
        auto cur = Q[start++];
        for(int dir=0; dir<4; dir++){
            position nextpos = board.jump(cur.first, dir);
            if(fromStart[0][id][nextpos.y][nextpos.x] == MAX){
                fromStart[0][id][nextpos.y][nextpos.x] = cur.second+1;
                Q[end++] = {nextpos, cur.second+1};
            }
        }
    }
}

struct state{
    position pos;
    int size;
    bool operator<(const state& b) const{
        return size > b.size;
    }
};

void normalize(vector<vector<int>>& A){
    priority_queue<state> prioQ;
    for(int y=0; y<h; y++){
        for(int x=0; x<w; x++){
            if(A[y][x] >= MAX)continue;
            position curpos = {x, y};
            prioQ.push({curpos, A[y][x]});
        }
    }
    while(!prioQ.empty()){
        state cur=prioQ.top();
        prioQ.pop();
        if(cur.size > A[cur.pos.y][cur.pos.x])continue;
        A[cur.pos.y][cur.pos.x] = cur.size;
        for(int dir=0; dir<4; dir++){
            state next = {board.jump(cur.pos, dir), cur.size+1};
            if(next.size < A[next.pos.y][next.pos.x]){
                A[next.pos.y][next.pos.x] = next.size;
                prioQ.push(next);
            }
        }
    }
}

void fuse(int start, int end){
    //cout << start << " " << end << '\n';
    int span = end-start-1;
    for(int mid=start+1; mid<end; mid++){
        for(int y=0; y<h; y++){
            for(int x=0; x<w; x++){
                fromStart[span][start][y][x] = min(
                    fromStart[span][start][y][x],
                    fromStart[mid-start-1][start][y][x] + fromStart[end-mid-1][mid][y][x]
                );
            }
        }
    }
    normalize(fromStart[span][start]);
    //for(int y=0; y<h; y++){
    //    for(int x=0; x<w; x++){
    //        cout << fromStart[span][start][y][x] << '\t';
    //    }
    //    cout << '\n';
    //}
}

int main(){
    ios_base::sync_with_stdio(false);cin.tie(0);
    cin >> n >> w >> h;
    board = Board(w, h, n);
    MAX = n*w*h;
    board.read();
    Q.resize(w*h);
    fromStart.resize(n);
    for(int i=0; i<n; i++){
        fromStart[i] = vector<vector<vector<int>>>(n-i,
                              vector<vector<int>> (h,
                                     vector<int>  (w, MAX)));
    }
    //board.jump(board.bots[1], 0).print();
    //board.bots[1].forward(0).print();
    //board.jump(board.bots[3], 1).print();
    //board.jump(board.bots[2], 1).print();
    for(int i=0; i<n; i++){
        bfs(board.bots[i], i);
    }
    for(int i=1; i<n; i++){
        for(int start=0; start <= n-i-1; start++){
            fuse(start, start+i+1);
        }
    }
    int res = w*h*n;
    for(int y=0; y<h; y++){
        for(int x=0; x<w; x++){
            res = min(res, fromStart[n-1][0][y][x]);
        }
        //cout << '\n';
    }
    if(res >= MAX){
        cout << "-1\n";
    }else
        cout << res << '\n';
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…