提出 #66918353


ソースコード 拡げる

#include <bits/stdc++.h>
using namespace std;

// AtCoder Heuristic: Durability-Constrained Transport
// Beam Search Implementation with case-based heuristics
// Compile: g++ -std=c++17 -O2 main.cpp

constexpr int N = 20;
constexpr int MAX_BOX = N*N - 1;   // 399
constexpr int BEAM_W = 64;         // Beam width
constexpr int OP_LIMIT = 16000;    // Max operations (move+pick+drop)

struct Box { int x, y, w, d; };
vector<Box> boxes;
int dist0[N][N];  // Manhattan from (0,0)

struct Held { int id, rem; };
struct State {
    int px=0, py=0;                 // current position
    int ops=0;                      // all ops count
    int moves=0;                    // move count
    array<uint64_t,7> mask{};       // remaining boxes
    vector<Held> stack;             // carried stack
    string log;                     // operations log
    int score=0;                    // heuristic score
};

inline bool has_box(const State &s, int id) {
    return s.mask[id>>6] & (1ULL<<(id&63));
}
inline void remove_box(State &s, int id) {
    s.mask[id>>6] &= ~(1ULL<<(id&63));
}
inline bool all_removed(const State &s) {
    for(auto m: s.mask) if(m) return false;
    return true;
}

// Step one move, update durability, count ops
bool step(State &st, char dir) {
    if(st.ops >= OP_LIMIT) return false;
    st.log.push_back(dir);
    st.ops++; st.moves++;
    if(dir=='U') st.px--;
    else if(dir=='D') st.px++;
    else if(dir=='L') st.py--;
    else if(dir=='R') st.py++;
    if(st.stack.empty()) return true;
    int above = 0;
    for(int i=(int)st.stack.size()-1; i>=0; --i) {
        st.stack[i].rem -= above;
        if(st.stack[i].rem <= 0) return false;
        above += boxes[st.stack[i].id].w;
    }
    return true;
}

bool move_to(State &st, int nx, int ny) {
    while(st.px < nx) if(!step(st,'D')) return false;
    while(st.px > nx) if(!step(st,'U')) return false;
    while(st.py < ny) if(!step(st,'R')) return false;
    while(st.py > ny) if(!step(st,'L')) return false;
    return true;
}

// Heuristic evaluation combining multiple criteria
int evaluate(const State &st) {
    long long val = 0;
    // 1. remaining boxes near origin
    long long sumDist = 0;
    for(int id=0; id<MAX_BOX; ++id) if(has_box(st,id)) {
        auto &b = boxes[id]; sumDist += dist0[b.x][b.y];
    }
    val -= sumDist;
    // 2. number carried
    val += (long long)st.stack.size() * 500;
    // 3. average durability ratio of carried: (d/w)
    if(!st.stack.empty()) {
        double avgRatio = 0;
        for(auto &h: st.stack)
            avgRatio += (double)h.rem / boxes[h.id].w;
        avgRatio /= st.stack.size();
        val += (int)(avgRatio * 100);
    }
    // 4. penalize moves
    val -= st.moves * 5;
    return (int)val;
}

// Beam expansion
vector<State> expand(const State &cur) {
    vector<State> nxt;
    // auto-drop at origin
    if (!cur.stack.empty() && cur.px==0 && cur.py==0) {
        State ns = cur;
        if (ns.ops+1 <= OP_LIMIT) {
            ns.ops++;          // automatic drop, no log
            ns.stack.clear();
            ns.score = evaluate(ns);
            nxt.push_back(move(ns));
        }
        return nxt;
    }
    // case: no box in hand -> pick farthest K in SE, else all
    if (cur.stack.empty()) {
        const int K = 4;
        vector<pair<int,int>> cand;
        for (int id=0; id<MAX_BOX; ++id) if (has_box(cur,id)) {
            auto &b = boxes[id];
            if (b.x>=cur.px && b.y>=cur.py) {
                int d = abs(cur.px-b.x)+abs(cur.py-b.y);
                cand.emplace_back(d,id);
            }
        }
        if (cand.empty()) {
            for (int id=0; id<MAX_BOX; ++id) if (has_box(cur,id)) {
                auto &b = boxes[id];
                int d = abs(cur.px-b.x)+abs(cur.py-b.y);
                cand.emplace_back(d,id);
            }
        }
        sort(cand.begin(),cand.end(),greater<>());
        int take = min(K,(int)cand.size());
        for (int i=0; i<take; ++i) {
            int id = cand[i].second;
            State ns = cur;
            if (!move_to(ns, boxes[id].x, boxes[id].y)) continue;
            if (ns.ops+1 > OP_LIMIT) continue;
            // simulate stacking durability
            int remSteps = dist0[boxes[id].x][boxes[id].y];
            int above=0;
            for (int j=(int)ns.stack.size()-1; j>=0; --j) above+=boxes[ns.stack[j].id].w;
            bool ok=true;
            for (auto &h: ns.stack) {
                if (h.rem < above*remSteps) { ok=false; break; }
            }
            if (!ok) continue;
            // perform pick
            ns.stack.push_back({id, boxes[id].d});
            remove_box(ns,id);
            ns.log.push_back('1'); ns.ops++;
            // ensure return to origin is possible
            {
                State tmp = ns;
                if (!move_to(tmp,0,0)) continue;
            }
            ns.score = evaluate(ns);
            nxt.push_back(move(ns));
        }
    } else {
        // case: carrying -> pick NW candidates or return
        const int K2 = 2;
        vector<pair<double,int>> cand;
        for (int id=0; id<MAX_BOX; ++id) if (has_box(cur,id)) {
            auto &b = boxes[id];
            if (b.x < cur.px && b.y < cur.py) {
                double ratio = double(b.d)/b.w;
                int d = abs(cur.px-b.x)+abs(cur.py-b.y);
                cand.emplace_back(ratio-d*0.1, id);
            }
        }
        if (cand.empty()) {
            for (int id=0; id<MAX_BOX; ++id) if (has_box(cur,id)) {
                auto &b = boxes[id];
                double ratio = double(b.d)/b.w;
                int d = abs(cur.px-b.x)+abs(cur.py-b.y);
                cand.emplace_back(ratio-d*0.1, id);
            }
        }
        sort(cand.begin(), cand.end(), greater<>());
        int take2 = min(K2, (int)cand.size());
        for (int i=0; i<take2; ++i) {
            int id = cand[i].second;
            State ns = cur;
            if (!move_to(ns, boxes[id].x, boxes[id].y)) continue;
            if (ns.ops+1 > OP_LIMIT) continue;
            // staging: simulate return emptiness
            bool reach=false;
            int tx=ns.px, ty=ns.py;
            while (tx>0 || ty>0) {
                if (tx>0) tx--; else if (ty>0) ty--;
                int bid=-1;
                for (int z=0; z<MAX_BOX; ++z) if (boxes[z].x==tx && boxes[z].y==ty && has_box(ns,z)) { bid=z; break; }
                if (bid<0) { reach=true; break; }
            }
            if (!reach) continue;
            // durability check
            int remSteps = dist0[boxes[id].x][boxes[id].y];
            int above=0;
            for (int j=(int)ns.stack.size()-1;j>=0;--j) above+=boxes[ns.stack[j].id].w;
            bool ok=true;
            for (auto &h: ns.stack) if (h.rem < above*remSteps) { ok=false; break; }
            if (!ok) continue;
            ns.stack.push_back({id, boxes[id].d});
            remove_box(ns,id);
            ns.log.push_back('1'); ns.ops++;
            // ensure return
            {
                State tmp=ns;
                if (!move_to(tmp,0,0)) continue;
            }
            ns.score = evaluate(ns);
            nxt.push_back(move(ns));
        }
        // return & auto-drop
        {
            State ns=cur;
            if(move_to(ns,0,0) && !ns.stack.empty() && ns.ops+1<=OP_LIMIT) {
                ns.ops++;
                ns.stack.clear();
                ns.score = evaluate(ns);
                nxt.push_back(move(ns));
            }
        }
    }
    return nxt;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n; cin>>n;
    vector<vector<int>> wg(n,vector<int>(n)), dg(n,vector<int>(n));
    for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>wg[i][j];
    for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>dg[i][j];
    boxes.reserve(MAX_BOX);
    for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i||j)
        boxes.push_back({i,j,wg[i][j],dg[i][j]});
    for(int i=0;i<n;i++) for(int j=0;j<n;j++) dist0[i][j] = i+j;
    State init;
    init.mask.fill(0);
    for(int id=0;id<MAX_BOX;++id) init.mask[id>>6] |= 1ULL<<(id&63);
    init.score = evaluate(init);

    vector<State> beam{init}, buf;
    beam.reserve(BEAM_W);
    buf.reserve(BEAM_W*4);
    while(!beam.empty()){
        buf.clear();
        for(auto &s: beam){
            auto v = expand(s);
            for(auto &ns: v) buf.push_back(move(ns));
        }
        if(buf.empty()) break;
        nth_element(buf.begin(), buf.begin()+min((int)buf.size(),BEAM_W), buf.end(),
                    [](auto &a, auto &b){ return a.score > b.score; });
        beam.assign(buf.begin(), buf.begin()+min((int)buf.size(),BEAM_W));
        if(all_removed(beam[0]) && beam[0].stack.empty()) break;
    }
    for(char c: beam[0].log) cout<<c<<"\n";
    return 0;
}

提出情報

提出日時
問題 A - Durability-Constrained Transport
ユーザ koshinM
言語 C++ 17 (gcc 12.2)
得点 675574
コード長 9034 Byte
結果 AC
実行時間 367 ms
メモリ 11700 KiB

ジャッジ結果

セット名 test_ALL
得点 / 配点 675574 / 2460000
結果
AC × 150
セット名 テストケース
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
ケース名 結果 実行時間 メモリ
test_0000.txt AC 325 ms 10956 KiB
test_0001.txt AC 335 ms 11552 KiB
test_0002.txt AC 337 ms 11308 KiB
test_0003.txt AC 321 ms 11100 KiB
test_0004.txt AC 293 ms 10332 KiB
test_0005.txt AC 347 ms 11420 KiB
test_0006.txt AC 340 ms 11236 KiB
test_0007.txt AC 298 ms 10852 KiB
test_0008.txt AC 303 ms 10852 KiB
test_0009.txt AC 322 ms 11580 KiB
test_0010.txt AC 358 ms 11516 KiB
test_0011.txt AC 315 ms 11180 KiB
test_0012.txt AC 306 ms 10776 KiB
test_0013.txt AC 306 ms 11320 KiB
test_0014.txt AC 310 ms 11176 KiB
test_0015.txt AC 315 ms 11392 KiB
test_0016.txt AC 317 ms 11264 KiB
test_0017.txt AC 323 ms 11508 KiB
test_0018.txt AC 311 ms 11332 KiB
test_0019.txt AC 328 ms 10812 KiB
test_0020.txt AC 308 ms 10688 KiB
test_0021.txt AC 324 ms 10084 KiB
test_0022.txt AC 299 ms 10568 KiB
test_0023.txt AC 318 ms 10904 KiB
test_0024.txt AC 325 ms 11168 KiB
test_0025.txt AC 321 ms 11220 KiB
test_0026.txt AC 340 ms 11408 KiB
test_0027.txt AC 325 ms 10856 KiB
test_0028.txt AC 310 ms 11124 KiB
test_0029.txt AC 327 ms 11260 KiB
test_0030.txt AC 314 ms 11312 KiB
test_0031.txt AC 320 ms 11316 KiB
test_0032.txt AC 325 ms 11396 KiB
test_0033.txt AC 326 ms 11540 KiB
test_0034.txt AC 305 ms 11120 KiB
test_0035.txt AC 319 ms 10564 KiB
test_0036.txt AC 342 ms 11232 KiB
test_0037.txt AC 315 ms 10864 KiB
test_0038.txt AC 348 ms 11620 KiB
test_0039.txt AC 302 ms 11312 KiB
test_0040.txt AC 309 ms 11072 KiB
test_0041.txt AC 319 ms 11412 KiB
test_0042.txt AC 344 ms 11204 KiB
test_0043.txt AC 310 ms 11384 KiB
test_0044.txt AC 311 ms 10712 KiB
test_0045.txt AC 314 ms 11292 KiB
test_0046.txt AC 326 ms 11396 KiB
test_0047.txt AC 310 ms 10624 KiB
test_0048.txt AC 305 ms 10724 KiB
test_0049.txt AC 301 ms 10852 KiB
test_0050.txt AC 292 ms 10392 KiB
test_0051.txt AC 307 ms 11220 KiB
test_0052.txt AC 330 ms 11036 KiB
test_0053.txt AC 325 ms 10736 KiB
test_0054.txt AC 304 ms 10748 KiB
test_0055.txt AC 346 ms 10652 KiB
test_0056.txt AC 299 ms 10736 KiB
test_0057.txt AC 309 ms 10896 KiB
test_0058.txt AC 313 ms 10440 KiB
test_0059.txt AC 353 ms 11480 KiB
test_0060.txt AC 316 ms 11304 KiB
test_0061.txt AC 325 ms 11288 KiB
test_0062.txt AC 323 ms 11300 KiB
test_0063.txt AC 326 ms 11360 KiB
test_0064.txt AC 306 ms 11036 KiB
test_0065.txt AC 317 ms 11308 KiB
test_0066.txt AC 316 ms 11272 KiB
test_0067.txt AC 301 ms 10620 KiB
test_0068.txt AC 319 ms 11356 KiB
test_0069.txt AC 307 ms 11108 KiB
test_0070.txt AC 304 ms 10524 KiB
test_0071.txt AC 316 ms 11340 KiB
test_0072.txt AC 337 ms 11280 KiB
test_0073.txt AC 326 ms 11288 KiB
test_0074.txt AC 294 ms 10236 KiB
test_0075.txt AC 352 ms 11580 KiB
test_0076.txt AC 340 ms 10744 KiB
test_0077.txt AC 299 ms 10272 KiB
test_0078.txt AC 313 ms 11088 KiB
test_0079.txt AC 317 ms 11244 KiB
test_0080.txt AC 326 ms 11412 KiB
test_0081.txt AC 330 ms 11448 KiB
test_0082.txt AC 308 ms 10448 KiB
test_0083.txt AC 334 ms 11220 KiB
test_0084.txt AC 309 ms 10896 KiB
test_0085.txt AC 313 ms 10860 KiB
test_0086.txt AC 300 ms 10692 KiB
test_0087.txt AC 305 ms 10316 KiB
test_0088.txt AC 326 ms 11428 KiB
test_0089.txt AC 316 ms 11216 KiB
test_0090.txt AC 313 ms 11100 KiB
test_0091.txt AC 313 ms 11192 KiB
test_0092.txt AC 311 ms 11300 KiB
test_0093.txt AC 295 ms 10424 KiB
test_0094.txt AC 350 ms 11356 KiB
test_0095.txt AC 310 ms 10484 KiB
test_0096.txt AC 331 ms 11464 KiB
test_0097.txt AC 307 ms 11160 KiB
test_0098.txt AC 316 ms 11332 KiB
test_0099.txt AC 315 ms 11320 KiB
test_0100.txt AC 326 ms 10612 KiB
test_0101.txt AC 339 ms 10924 KiB
test_0102.txt AC 321 ms 11156 KiB
test_0103.txt AC 327 ms 11352 KiB
test_0104.txt AC 335 ms 10636 KiB
test_0105.txt AC 309 ms 10712 KiB
test_0106.txt AC 313 ms 11048 KiB
test_0107.txt AC 314 ms 11156 KiB
test_0108.txt AC 321 ms 11304 KiB
test_0109.txt AC 313 ms 11136 KiB
test_0110.txt AC 309 ms 11116 KiB
test_0111.txt AC 343 ms 11412 KiB
test_0112.txt AC 307 ms 11204 KiB
test_0113.txt AC 316 ms 11340 KiB
test_0114.txt AC 305 ms 11100 KiB
test_0115.txt AC 324 ms 11296 KiB
test_0116.txt AC 305 ms 10908 KiB
test_0117.txt AC 304 ms 10756 KiB
test_0118.txt AC 326 ms 10900 KiB
test_0119.txt AC 310 ms 11108 KiB
test_0120.txt AC 329 ms 11384 KiB
test_0121.txt AC 302 ms 11100 KiB
test_0122.txt AC 339 ms 11516 KiB
test_0123.txt AC 367 ms 11628 KiB
test_0124.txt AC 306 ms 11068 KiB
test_0125.txt AC 303 ms 10644 KiB
test_0126.txt AC 311 ms 11432 KiB
test_0127.txt AC 324 ms 11412 KiB
test_0128.txt AC 334 ms 11164 KiB
test_0129.txt AC 325 ms 11292 KiB
test_0130.txt AC 319 ms 11408 KiB
test_0131.txt AC 320 ms 11700 KiB
test_0132.txt AC 314 ms 11344 KiB
test_0133.txt AC 320 ms 11448 KiB
test_0134.txt AC 318 ms 11316 KiB
test_0135.txt AC 357 ms 11484 KiB
test_0136.txt AC 320 ms 11148 KiB
test_0137.txt AC 340 ms 11164 KiB
test_0138.txt AC 316 ms 10856 KiB
test_0139.txt AC 325 ms 11312 KiB
test_0140.txt AC 330 ms 11288 KiB
test_0141.txt AC 310 ms 10820 KiB
test_0142.txt AC 302 ms 10828 KiB
test_0143.txt AC 308 ms 10620 KiB
test_0144.txt AC 320 ms 11408 KiB
test_0145.txt AC 323 ms 11188 KiB
test_0146.txt AC 337 ms 10972 KiB
test_0147.txt AC 335 ms 11612 KiB
test_0148.txt AC 311 ms 11256 KiB
test_0149.txt AC 320 ms 11360 KiB