RCO presents 日本橋ハーフマラソン 本戦

Submission #1358450

Source codeソースコード

#pragma GCC optimize ("O3")
#pragma GCC target ("avx")
#include "bits/stdc++.h" // define macro "/D__MAI"

using namespace std;
typedef long long int ll;

#define debugv(v) printf("L%d %s => ",__LINE__,#v);for(auto e:v){cout<<e<<" ";}cout<<endl;
#define debugm(m) printf("L%d %s is..\n",__LINE__,#m);for(auto v:m){for(auto e:v){cout<<e<<" ";}cout<<endl;}
#define debuga(m,w) printf("L%d %s is => ",__LINE__,#m);for(int x=0;x<(w);x++){cout<<(m)[x]<<" ";}cout<<endl;
#define debugaa(m,w,h) printf("L%d %s is..\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[x][y]<<" ";}cout<<endl;}
#define debugaar(m,w,h) printf("L%d %s is..\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[y][x]<<" ";}cout<<endl;}
#define ALL(v) (v).begin(),(v).end()
#define repeat(l) for(auto cnt=0;cnt<(l);++cnt)
#define iterate(b,e) for(auto cnt=(b);cnt!=(e);++cnt)
#define MD 1000000007ll
#define PI 3.1415926535897932384626433832795
template<typename T1, typename T2>
ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << "(" << p.first << ":" << p.second << ")"; return o; }

#define TIME chrono::system_clock::now()
#define MILLISEC(t) (chrono::duration_cast<chrono::milliseconds>(t).count())
namespace {
    std::chrono::system_clock::time_point ttt;
    void tic() { ttt = TIME; }
    void toc() { fprintf(stderr, "TIME : %lldms\n", MILLISEC(TIME - ttt)); }
    std::chrono::system_clock::time_point tle = TIME;
#ifdef __MAI
    void safe_tle(int msec) { assert(MILLISEC(TIME - tle) < msec); }
#else
#define safe_tle(k) ;
#endif
}
#ifdef __MAI
#define getchar_unlocked getchar
#define putchar_unlocked putchar
#endif
#ifdef __VSCC
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#endif
namespace {
#define isvisiablechar(c) (0x21<=(c)&&(c)<=0x7E)
    class MaiScanner {
    public:
        template<typename T>
        void input_integer(T& var) {
            var = 0;
            T sign = 1;
            int cc = getchar_unlocked();
            for (; cc<'0' || '9'<cc; cc = getchar_unlocked())
                if (cc == '-') sign = -1;
            for (; '0' <= cc&&cc <= '9'; cc = getchar_unlocked())
                var = (var << 3) + (var << 1) + cc - '0';
            var = var*sign;
        }
        inline int c() { return getchar_unlocked(); }
        inline MaiScanner& operator>>(int& var) {
            input_integer<int>(var);
            return *this;
        }
        inline MaiScanner& operator>>(long long& var) {
            input_integer<long long>(var);
            return *this;
        }
        inline MaiScanner& operator>>(string& var) {
            int cc = getchar_unlocked();
            for (; !isvisiablechar(cc); cc = getchar_unlocked());
            for (; isvisiablechar(cc); cc = getchar_unlocked())
                var.push_back(cc);
        }
    };
    class MaiPrinter {
        int stack_p;
        char stack[32];
    public:
        template<typename T>
        void output_integer(T var) {
            if (var == 0) {
                putchar_unlocked('0');
                return;
            }
            if (var < 0) {
                putchar_unlocked('-');
                var = -var;
            }
            stack_p = 0;
            while (var) {
                stack[stack_p++] = '0' + (var % 10);
                var /= 10;
            }
            while (stack_p)
                putchar_unlocked(stack[--stack_p]);
        }
        inline MaiPrinter& operator<<(char c) {
            putchar_unlocked(c);
            return *this;
        }
        inline MaiPrinter& operator<<(int var) {
            output_integer<int>(var);
            return *this;
        }
        inline MaiPrinter& operator<<(long long var) {
            output_integer<long long>(var);
            return *this;
        }
        inline MaiPrinter& operator<(int var) {
            output_integer<int>(var);
            putchar_unlocked(' ');
            return *this;
        }
        inline MaiPrinter& operator<(long long var) {
            output_integer<long long>(var);
            putchar_unlocked(' ');
            return *this;
        }
        inline MaiPrinter& operator<<(const string& str) {
            const char* p = str.c_str();
            const char* l = p + str.size();
            while (p < l) putchar_unlocked(*p++);
            return *this;
        }
    };
}
MaiScanner scanner;
MaiPrinter printer;



random_device noize;
mt19937 mt(noize());

int rand_int(int l, int h) {
    uniform_int_distribution<> range(l, h);
    return range(mt);
}


class Flow {
public:
    size_t n;
    struct Arrow {
        int from, to;
        int left;
        int cap;

        Arrow(int from = 0, int to = 0, int w = 1) :from(from), to(to), left(w), cap(w) {}
        bool operator<(const Arrow& a) const { return (from<a.from) | (to<a.to) | (left<a.left) | (cap<a.cap); }
        bool operator==(const Arrow& a) const { return (from == a.from) && (to == a.to) && (left == a.left) && (cap == a.cap); }
    };
    vector<vector<int>> vertex_to;
    vector<vector<int>> vertex_from;
    vector<Arrow> arrow;

    Flow(int n, int m = 5010) :n(n), vertex_to(n), vertex_from(n) { arrow.reserve(m); }

    void connect(int from, int to, int left) {
        vertex_to[from].push_back(arrow.size()); // toto
        vertex_from[to].push_back(arrow.size()); // fromfrom
        arrow.emplace_back(from, to, left);
    }
    size_t degree(int v) {
        return vertex_to[v].size() + vertex_from[v].size();
    }
    size_t degree_in(int v) {
        return vertex_from[v].size();
    }
    size_t degree_out(int v) {
        return vertex_to[v].size();
    }
};
int _dinic_path_dfs(Flow& flow, vector<int>& result, vector<int>& flag, const vector<int>& dist, int u, int i_sink, int mini) {
    // TODO: 経路再利用
    if (i_sink == u) return mini;
    if (flag[u]) return -1;
    flag[u] = true;

    int sumw = 0;
    bool term = true;
    for (int e : flow.vertex_to[u]) {
        Flow::Arrow& a = flow.arrow[e];
        if (a.left > 0 && dist[u]>dist[a.to]) {
            int w;
            if (mini < 0)
                w = a.left;
            else
                w = min(a.left, mini);

            w = _dinic_path_dfs(flow, result, flag, dist, a.to, i_sink, w);
            if (w == -1) continue;
            a.left -= w;
            result[a.to] += w;

            sumw += w;
            mini -= w;
            term = false;
            flag[u] = false; // TODO: 末尾では? 

            if (mini == 0) return term ? -1 : sumw;
        }
    }
    for (int e : flow.vertex_from[u]) {
        Flow::Arrow& a = flow.arrow[e];
        if (a.cap>a.left && dist[u]>dist[a.from]) {
            int w;
            if (mini < 0)
                w = a.cap - a.left;
            else
                w = min(a.cap - a.left, mini);

            w = _dinic_path_dfs(flow, result, flag, dist, a.from, i_sink, w);
            if (w == -1) continue;
            a.left += w;
            result[a.to] -= w;

            sumw += w;
            mini -= w;
            term = false;
            flag[u] = false;
            if (mini == 0) return term ? -1 : sumw;
        }
    }
    return term ? -1 : sumw;
}

// flowは書き換えられる.
void dinic(Flow &flow, vector<int>& result, int i_source, int i_sink) {
    assert(i_source != i_sink);

    result.resize(flow.n);

    int distbegin = 0;
    vector<int> dist(flow.n);
    queue<int> q;
    vector<int> flag(flow.n);
    for (int distbegin = 0; ; distbegin += flow.n) {

        q.emplace(i_sink); // bfsはsinkからsourceへの距離を計算.
        dist[i_sink] = distbegin + 1;
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int ie : flow.vertex_from[v]) {
                const Flow::Arrow& e = flow.arrow[ie];
                if (0<e.left && dist[e.from] <= distbegin) {
                    dist[e.from] = dist[v] + 1;
                    q.emplace(e.from);
                }
            }
            for (int ie : flow.vertex_to[v]) {
                const Flow::Arrow& e = flow.arrow[ie];
                if (e.left<e.cap && dist[e.to] <= distbegin) {
                    dist[e.to] = dist[v] + 1;
                    q.emplace(e.to);
                }
            }
        }
        //debugv(dist);
        fill(ALL(flag), false);

        if (dist[i_source] <= distbegin) {
            break;
        }
        else {
            result[i_source] += _dinic_path_dfs(flow, result, flag, dist, i_source, i_sink, -1);
        }
    }

}



#define cv_d2i(y,x) ((y)*width+(x))

int height = 30, width = 30, n = 450, t_limit = 10000;

inline bool isscreenout(int y, int x) {
    return y < 0 || x < 0 || height <= y || width <= x;
}

inline char actvel2char(int vy, int vx) {
    return vx < 0 ? 'L' : vx>0 ? 'R' : vy < 0 ? 'U' : vy>0 ? 'D' : '-';
}

inline void actchar(int &y, int &x, int c) {
    if (c == 'L') --x;
    else if (c == 'R') ++x;
    else if (c == 'U') --y;
    else if (c == 'D') ++y;
}


class Car {
public:
    int y, x, dy, dx;
    Car(int y = 0, int x = 0, int dy = 0, int dx = 0) :y(y), x(x), dy(dy), dx(dx) {}
};

class State {
public:
    vector<int> data;
    vector<Car> cars;
    string acts;
    int turn;

    State() :data(width*height, -1), cars(n), acts(n, '-') {  }

    inline int& operator()(int y, int x) {
        return data[x + y*width];
    }
    inline int operator()(int y, int x) const {
        return data[x + y*width];
    }
    inline int& at(int y, int x) {
        return data[x + y*width];
    }
    inline int at(int y, int x) const {
        return data[x + y*width];
    }

    void put(int carid, int y, int x, int dx, int dy) {
        at(y, x) = carid;
        cars[carid] = Car(y, x, dx, dy);
    }

    bool action(int carid, int vy, int vx) {
        const Car& car = cars[carid];
        if (isscreenout(car.y + vy, car.x + vx)) return false;
        int& to = at(car.y + vy, car.x + vx);
        if (to != -1) return false;
        to = -2 - carid;
        acts[carid] = actvel2char(vy, vx);
        return true;
    }

    int act_count() const {
        int cnt = 0;
        for (char c : acts) {
            cnt += (c != '-');
        }
        return cnt;
    }

    // bool print() const {
    //     string s;
    //     bool b = false;
    //     for (char c : acts) {
    //         if (b |= (c != '-')) break;
    //     }
    //     if (!b) return false;
    //     printer << acts << '\n';
    //     return true;
    // }

    void eprint() const {
        printf("---\n");
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                printf("%4d", at(y, x));
            }
            printf("\n");
        }
    }

    State next_state() const {
        State new_state = *this;

        new_state.turn += 1;

        for (int i = 0; i < n; ++i) {
            Car &car = new_state.cars[i];

            new_state.at(car.y, car.x) = -1;
            actchar(car.y, car.x, new_state.acts[i]);
            new_state.at(car.y, car.x) = i;
        }
        fill(ALL(new_state.acts), '-');

        return new_state;
    }

    int score() const{

    }
};



State first_state;

list<State> result;

void solve_greedy(int count, const State& first) {

    State state = first;

    repeat(t_limit) {
        for (int i = 0; i < n; ++i) {
            Car &car = state.cars[i];
            int uy = car.dy - car.y;
            int ux = car.dx - car.x;
            
            bool pr = rand_int(0, 1);
            if (uy != 0 && (ux == 0 || pr)) {
                if (uy > 0) pr = state.action(i, 1, 0);
                else pr = state.action(i, -1, 0);
            }
            if (ux != 0 && (uy == 0 || !pr)) {
                if (ux > 0) state.action(i, 0, 1);
                else state.action(i, 0, -1);
            }
        }
        //state.eprint();

        if (state.act_count() < 10) break;

        result.push_back(state);

        state = state.next_state();
    }
}

void solve_zigzag1() {

    vector<int> r_flow;

    vector<int> used(height*width, -1);
    vector<int> edgelabel(20000);

    State state = first_state;

    repeat(40) {
        Flow flow(height*width + 2);
        const int tail = height*width;

        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                if ((y + x) % 2 == state.turn % 2) continue;
                int carid = state(y, x);
                if (carid == -1)continue;

                Car &car = state.cars[carid];
                int uy = car.dy - car.y;
                int ux = car.dx - car.x;

                bool pr = rand_int(0, 1);

                flow.connect(tail, cv_d2i(y, x), 1);

                if (uy <= 0)
                    if (!isscreenout(y - 1, x) && state(y - 1, x) == -1) {
                        edgelabel[flow.arrow.size()] = 'U';
                        flow.connect(cv_d2i(y, x), cv_d2i(y - 1, x), 1);
                        if (used[cv_d2i(y - 1, x)] < cnt) {
                            used[cv_d2i(y - 1, x)] = cnt;
                            flow.connect(cv_d2i(y - 1, x), tail + 1, 1);
                        }
                    }
                if (uy >= 0)
                    if (!isscreenout(y + 1, x) && state(y + 1, x) == -1) {
                        edgelabel[flow.arrow.size()] = 'D';
                        flow.connect(cv_d2i(y, x), cv_d2i(y + 1, x), 1);
                        if (used[cv_d2i(y + 1, x)] < cnt) {
                            used[cv_d2i(y + 1, x)] = cnt;
                            flow.connect(cv_d2i(y + 1, x), tail + 1, 1);
                        }
                    }
                if (ux <= 0)
                    if (!isscreenout(y, x - 1) && state(y, x - 1) == -1) {
                        edgelabel[flow.arrow.size()] = 'L';
                        flow.connect(cv_d2i(y, x), cv_d2i(y, x - 1), 1);
                        if (used[cv_d2i(y, x - 1)] < cnt) {
                            used[cv_d2i(y, x - 1)] = cnt;
                            flow.connect(cv_d2i(y, x - 1), tail + 1, 1);
                        }
                    }
                if (ux >= 0)
                    if (!isscreenout(y, x + 1) && state(y, x + 1) == -1) {
                        edgelabel[flow.arrow.size()] = 'R';
                        flow.connect(cv_d2i(y, x), cv_d2i(y, x + 1), 1);
                        if (used[cv_d2i(y, x + 1)] < cnt) {
                            used[cv_d2i(y, x + 1)] = cnt;
                            flow.connect(cv_d2i(y, x + 1), tail + 1, 1);
                        }
                    }

            }
        }
        dinic(flow, r_flow, tail, tail + 1);

        for (int ai : flow.vertex_to[tail]) {
            int z = flow.arrow[ai].to;
            int x = z%width;
            int y = z/width;
            for (int aii : flow.vertex_to[z]) {
                if (flow.arrow[aii].left == 0) {
                    state.acts[state.data[z]] = edgelabel[aii];
                    break;
                }
            }
        }
        result.push_back(state);

        state = state.next_state();
    }
    solve_greedy(5, state);
}

int main(int argc, char** argv) {

    scanner >> height >> width >> n >> t_limit;

    first_state.turn = 1;

    repeat(n) {
        int a, b, c, d;
        scanner >> a >> b >> c >> d;
        first_state.put(cnt, --a, --b, --c, --d);
    }

    // solve_greedy();

    solve_zigzag1();


    printer << (int)result.size() << '\n';

    for (State& s : result) {
        printer << s.acts << '\n';
    }
    

    return 0;
}

Submission

Task問題 B - 日本橋大渋滞
User nameユーザ名 舞葉舞
Created time投稿日時
Language言語 C++14 (GCC 5.4.1)
Status状態 AC
Score得点 5170
Source lengthソースコード長 16157 Byte
File nameファイル名
Exec time実行時間 10 ms
Memory usageメモリ使用量 1024 KB

Compiler messageコンパイルメッセージ

./Main.cpp: In function ‘void {anonymous}::toc()’:
./Main.cpp:26:73: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘std::chrono::duration<long int, std::ratio<1l, 1000l> >::rep {aka long int}’ [-Wformat=]
void toc() { fprintf(stderr, "TIME : %lldms\n", MILLISEC(TIME - ttt)); }
^

Test case

Set

Set name Score得点 / Max score Cases
test_01 181 / 50000 subtask_01_01.txt
test_02 190 / 50000 subtask_01_02.txt
test_03 180 / 50000 subtask_01_03.txt
test_04 181 / 50000 subtask_01_04.txt
test_05 191 / 50000 subtask_01_05.txt
test_06 177 / 50000 subtask_01_06.txt
test_07 179 / 50000 subtask_01_07.txt
test_08 186 / 50000 subtask_01_08.txt
test_09 167 / 50000 subtask_01_09.txt
test_10 165 / 50000 subtask_01_10.txt
test_11 186 / 50000 subtask_01_11.txt
test_12 172 / 50000 subtask_01_12.txt
test_13 160 / 50000 subtask_01_13.txt
test_14 182 / 50000 subtask_01_14.txt
test_15 162 / 50000 subtask_01_15.txt
test_16 193 / 50000 subtask_01_16.txt
test_17 168 / 50000 subtask_01_17.txt
test_18 170 / 50000 subtask_01_18.txt
test_19 159 / 50000 subtask_01_19.txt
test_20 167 / 50000 subtask_01_20.txt
test_21 176 / 50000 subtask_01_21.txt
test_22 167 / 50000 subtask_01_22.txt
test_23 162 / 50000 subtask_01_23.txt
test_24 155 / 50000 subtask_01_24.txt
test_25 165 / 50000 subtask_01_25.txt
test_26 169 / 50000 subtask_01_26.txt
test_27 171 / 50000 subtask_01_27.txt
test_28 160 / 50000 subtask_01_28.txt
test_29 166 / 50000 subtask_01_29.txt
test_30 163 / 50000 subtask_01_30.txt

Test case

Case name Status状態 Exec time実行時間 Memory usageメモリ使用量
subtask_01_01.txt AC 9 ms 1024 KB
subtask_01_02.txt AC 10 ms 1024 KB
subtask_01_03.txt AC 9 ms 1024 KB
subtask_01_04.txt AC 9 ms 1024 KB
subtask_01_05.txt AC 10 ms 1024 KB
subtask_01_06.txt AC 9 ms 1024 KB
subtask_01_07.txt AC 9 ms 1024 KB
subtask_01_08.txt AC 10 ms 1024 KB
subtask_01_09.txt AC 9 ms 1024 KB
subtask_01_10.txt AC 9 ms 1024 KB
subtask_01_11.txt AC 9 ms 1024 KB
subtask_01_12.txt AC 9 ms 1024 KB
subtask_01_13.txt AC 9 ms 1024 KB
subtask_01_14.txt AC 10 ms 1024 KB
subtask_01_15.txt AC 9 ms 1024 KB
subtask_01_16.txt AC 10 ms 1024 KB
subtask_01_17.txt AC 9 ms 1024 KB
subtask_01_18.txt AC 9 ms 1024 KB
subtask_01_19.txt AC 8 ms 896 KB
subtask_01_20.txt AC 8 ms 1024 KB
subtask_01_21.txt AC 9 ms 1024 KB
subtask_01_22.txt AC 9 ms 1024 KB
subtask_01_23.txt AC 9 ms 1024 KB
subtask_01_24.txt AC 8 ms 1024 KB
subtask_01_25.txt AC 9 ms 1024 KB
subtask_01_26.txt AC 9 ms 1024 KB
subtask_01_27.txt AC 9 ms 1024 KB
subtask_01_28.txt AC 9 ms 1024 KB
subtask_01_29.txt AC 9 ms 1024 KB
subtask_01_30.txt AC 9 ms 1024 KB