結果
| 問題 | 
                            No.2328 Build Walls
                             | 
                    
| コンテスト | |
| ユーザー | 
                             | 
                    
| 提出日時 | 2023-06-23 19:33:39 | 
| 言語 | D  (dmd 2.109.1)  | 
                    
| 結果 | 
                             
                                MLE
                                 
                             
                            
                         | 
                    
| 実行時間 | - | 
| コード長 | 4,096 bytes | 
| コンパイル時間 | 3,748 ms | 
| コンパイル使用メモリ | 182,384 KB | 
| 実行使用メモリ | 558,992 KB | 
| 最終ジャッジ日時 | 2024-06-30 23:11:07 | 
| 合計ジャッジ時間 | 22,662 ms | 
| 
                            ジャッジサーバーID (参考情報)  | 
                        judge5 / judge1 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 3 | 
| other | AC * 33 MLE * 1 | 
ソースコード
import std;
// ダイクストラ
// (H-2)*(W+1)の頂点をおいて、8方向に有向辺を張る
void read(T...)(string S, ref T args) {
    auto buf = S.split;
    foreach (i, ref arg; args) {
        arg = buf[i].to!(typeof(arg));
    }
}
void main () {
    int H, W; readln.read(H, W);
    int[][] A = new int[][](H-2, W);
    foreach (i; 0..H-2) {
        A[i] = readln.split.to!(int[]);
        A[i] = 0 ~ A[i];
    }
    solve(H, W, A);
}
struct pair {
    int x;
    int y;
}
bool isValid (int[][] A, int x, int y) {
    if (x < 0 || y < 0 || A.length <= y || A[0].length <= x) {
        return false;
    }
    if (A[y][x] == -1) {
        return false;
    }
    return true;
}
int toInt (pair X, int[][] A) {
    return cast(int) (X.x * A.length + X.y);
}
void connectPath (ref Dijkstra G, int[][] A, int x, int y) {
    int[] dx = [-1, 0, 1];
    int[] dy = [-1, 0, 1];
    foreach (i; 0..dx.length) {
        foreach (j; 0..dy.length) {
            if (i == 1 && j == 1) {
                continue;
            }
            if (isValid(A, x+dx[i], y+dx[j])) {
                G.input(pair(x, y).toInt(A), pair(x+dx[i], y+dy[j]).toInt(A), A[y+dy[j]][x+dx[i]]);
            }
        }
    }
}
void solve (int H, int W, int[][] A) {
    auto G = Dijkstra((H+1)*(W+1));
    foreach (X; 0..cast(int)A[0].length) {
        foreach (Y; 0..cast(int)A.length) {
            if (A[Y][X] == -1) {
                continue;
            }
            connectPath(G, A, X, Y);
        }
    }
    long ans = long.max;
    G.calc(pair(0, 0).toInt(A));
    foreach (Y2; 0..H-2) {
        ans = min(ans, G.cost(pair(W, Y2).toInt(A)));
    }
    if (ans == long.max) {
        writeln(-1);
    } else {
        writeln(ans);
    }
}
struct Dijkstra {
    /* data */
    int[][] graph;
    long[int][] weight;
    bool is_calc = false;
    struct dijkstra_node {
        int vertex;
        long distance;
        int path;
    }
    dijkstra_node[] node;
    /* methods */
    this (int N) {
        assert(0 <= N);
        graph = new int[][](N, 0);
        node = new dijkstra_node[](N);
        weight.length = N;
        foreach (i; 0..N) {
            node[i] = dijkstra_node(i, long.max, i);
        }
    }
    // u, v must be 0-indexed integer.
    void input (int u, int v, long w) {
        assert(0 <= u);
        assert(0 <= v);
        assert(0 <= w);
        if (graph.length <= max(u, v)) {
            graph.length = max(u, v) + 1;
        }
        graph[u] ~= v;
        weight[u][v] = w;
        if (node.length <= max(u, v)) {
            node.length = max(u, v) + 1;
            node[u] = dijkstra_node(u, long.max, u);
            node[v] = dijkstra_node(v, long.max, v);
        }
    }
    void calc (int start) {
        assert(start < graph.length);
        if (is_calc) {
            foreach (ref x; node) {
                x.distance = long.max;
                x.path = x.vertex;
            }
        }
        node[start].distance = 0;
        BinaryHeap!(dijkstra_node[], "b.distance < a.distance") PQ = [];
        PQ.insert(node[start]);
        while (!PQ.empty) {
            auto begin = PQ.front; PQ.removeFront;
            if (node[begin.vertex].distance < begin.distance) {
                continue;
            }
            node[begin.vertex] = begin;
            foreach (ref x; graph[begin.vertex]) {
                if (node[begin.vertex].distance + weight[begin.vertex][x] < node[x].distance) {
                    node[x].distance = node[begin.vertex].distance + weight[begin.vertex][x];
                    node[x].path = begin.vertex;
                    PQ.insert(node[x]);
                }
            }
        }
    }
    int[] trace (int end) {
        DList!int Q;
        int v = end;
        while (node[v].path != v) {
            Q.insertFront(v);
            v = node[v].path;
        }
        Q.insertFront(v);
        int[] res;
        while (!Q.empty) {
            res ~= Q.front; Q.removeFront;
        }
        return res;
    }
    long cost (int end) {
        return node[end].distance;
    }
}