結果

問題 No.5003 物理好きクリッカー
ユーザー simansiman
提出日時 2018-12-07 11:28:46
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 2,683 ms / 10,000 ms
コード長 24,269 bytes
コンパイル時間 1,258 ms
実行使用メモリ 21,972 KB
スコア 257,145,248,825
平均クエリ数 10000.00
最終ジャッジ日時 2021-07-19 09:05:24
合計ジャッジ時間 91,813 ms
ジャッジサーバーID
(参考情報)
judge12 / judge10
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2,664 ms
21,864 KB
testcase_01 AC 2,662 ms
21,888 KB
testcase_02 AC 2,662 ms
21,684 KB
testcase_03 AC 2,660 ms
21,456 KB
testcase_04 AC 2,661 ms
21,828 KB
testcase_05 AC 2,661 ms
21,348 KB
testcase_06 AC 2,660 ms
21,324 KB
testcase_07 AC 2,659 ms
21,456 KB
testcase_08 AC 2,665 ms
21,672 KB
testcase_09 AC 2,662 ms
21,612 KB
testcase_10 AC 2,660 ms
21,840 KB
testcase_11 AC 2,662 ms
21,324 KB
testcase_12 AC 2,668 ms
21,876 KB
testcase_13 AC 2,664 ms
21,468 KB
testcase_14 AC 2,667 ms
21,792 KB
testcase_15 AC 2,663 ms
21,804 KB
testcase_16 AC 2,660 ms
21,360 KB
testcase_17 AC 2,664 ms
21,804 KB
testcase_18 AC 2,660 ms
21,840 KB
testcase_19 AC 2,660 ms
21,600 KB
testcase_20 AC 2,661 ms
21,672 KB
testcase_21 AC 2,667 ms
21,312 KB
testcase_22 AC 2,662 ms
21,456 KB
testcase_23 AC 2,660 ms
21,828 KB
testcase_24 AC 2,660 ms
21,612 KB
testcase_25 AC 2,662 ms
21,360 KB
testcase_26 AC 2,659 ms
21,852 KB
testcase_27 AC 2,662 ms
21,840 KB
testcase_28 AC 2,665 ms
21,612 KB
testcase_29 AC 2,683 ms
21,324 KB
testcase_30 AC 2,659 ms
21,360 KB
testcase_31 AC 2,659 ms
21,288 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <cassert>
#include <cmath>
#include <iostream>
#include <vector>
#include <string.h>

typedef long long ll;
using namespace std;

double TIME_LIMIT = 2.0;
const ll CYCLE_PER_SEC = 2700000000;

const int N = 10000;

const int NOTHING = -1;
const int CLICK = 0;
const int BUY = 1;
const int SELL = 2;
const int REINFORCE = 3;
const int ENHCLICK = 4;
const int BUY_HAND = 5;
const int BUY_LILY = 6;
const int BUY_FACTORY = 7;
const int BUY_CASINO = 8;
const int BUY_GRIMOIRE = 9;
const int BUY_NEXT = 10;
const int BUY_SAME = 11;
const int UPDATE_HAND = 12;
const int UPDATE_LILY = 13;
const int UPDATE_FACTORY = 14;
const int UPDATE_CASINO = 15;
const int UPDATE_GRIMOIRE = 16;
const int UPGRADE_FACTORY = 17;
const int SELL_HAND = 18;
const int SELL_LILY = 19;
const int SELL_FACTORY = 20;
const int SELL_CASINO = 21;
const int SELL_GRIMOIRE = 22;
const int SELL_SAME = 23;

const int HAND = 1;
const int LILY = 2;
const int FACTORY = 3;
const int CASINO = 4;
const int GRIMOIRE = 5;

const int BUY_OPERATIONS[7] = {
        NOTHING,
        BUY_HAND,
        BUY_LILY,
        BUY_FACTORY,
        BUY_CASINO,
        BUY_GRIMOIRE,
        NOTHING
};

const int UPDATE_OPERATIONS[7] = {
        NOTHING,
        UPDATE_HAND,
        UPDATE_LILY,
        UPDATE_FACTORY,
        UPDATE_CASINO,
        UPDATE_GRIMOIRE,
        NOTHING
};

const int SELL_OPERATIONS[7] = {
        NOTHING,
        SELL_HAND,
        SELL_LILY,
        SELL_FACTORY,
        SELL_CASINO,
        SELL_GRIMOIRE,
        NOTHING,
};

const int BONUS = 1;
const int FEVER = 2;
const int SALE = 3;

const int PRODUCTIVITY[6] = {
        1,
        1,
        10,
        120,
        2000,
        25000
};

const ll UPDATE_COST[6][6] = {
        {
                15,
                150,
                1500,
                15000,
                150000,
                1500000
        },
        {
                150,
                1500,
                15000,
                150000,
                1500000,
                15000000
        },
        {
                2000,
                20000,
                200000,
                2000000,
                20000000,
                200000000,
        },
        {
                15,
                150,
                1500,
                15000,
                150000,
                1500000
        },
        {
                15,
                150,
                1500,
                15000,
                150000,
                1500000
        },
        {
                15,
                150,
                1500,
                15000,
                150000,
                1500000
        },
};

unsigned long long xor128() {
    static unsigned long long rx = 123456789, ry = 362436069, rz = 521288629, rw = 88675123;
    unsigned long long rt = (rx ^ (rx << 11));
    rx = ry;
    ry = rz;
    rz = rw;
    return (rw = (rw ^ (rw >> 19)) ^ (rt ^ (rt >> 8)));
}

unsigned long long int getCycle() {
    unsigned int low, high;
    __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
    return ((unsigned long long int) low) | ((unsigned long long int) high << 32);
}

double getTime(unsigned long long int begin_cycle) {
    return (double) (getCycle() - begin_cycle) / CYCLE_PER_SEC;
}

ll factory_price[7][50];
ll update_cost[7][50];

int operations[N];
int bonus[N + 21];
ll startCycle;

int OPERATION_LENGTH = 150;

class CookieClicker {
public:

    void init(string events) {
        startCycle = getCycle();
        memset(operations, CLICK, sizeof(operations));
        memset(bonus, NOTHING, sizeof(bonus));

        for (int i = 0; i < N; i++) {
            switch (events[i]) {
                case 'B':
                    bonus[i] = BONUS;
                    break;
                case 'F':
                    for (int j = i + 1; j <= i + 20; j++) {
                        bonus[j] = FEVER;
                    }
                    break;
                case 'S':
                    bonus[i + 1] = SALE;
                    break;
            }
        }

        int prices[6] = {
                0,
                150,
                2000,
                30000,
                600000,
                10000000
        };

        for (int i = 1; i <= 5; i++) {
            ll price = prices[i];
            ll cost = 10 * prices[i];

            for (int j = 0; j < 19; j++) {
                update_cost[i][j] = cost;
                cost *= 10;
            }

            for (int j = 0; j < 50; j++) {
                factory_price[i][j] = price;
                price = ceil((6 * price) / 5) + 1;
            }
        }
    }

    vector<int> firstAnswer() {
        vector<int> actions;

        actions.push_back(ENHCLICK);
        actions.push_back(ENHCLICK);
        actions.push_back(BUY_NEXT);
        for (int i = 0; i < 5; i++) {
            actions.push_back(BUY_SAME);
            actions.push_back(NOTHING);
        }

        actions.push_back(BUY_NEXT);
        for (int i = 0; i < 5; i++) {
            actions.push_back(BUY_SAME);
            actions.push_back(NOTHING);
        }
        actions.push_back(UPGRADE_FACTORY);

        actions.push_back(BUY_NEXT);
        for (int i = 0; i < 5; i++) {
            actions.push_back(BUY_SAME);
            actions.push_back(NOTHING);
        }
        actions.push_back(UPGRADE_FACTORY);

        actions.push_back(BUY_NEXT);
        for (int i = 0; i < 5; i++) {
            actions.push_back(BUY_SAME);
            actions.push_back(NOTHING);
        }
        actions.push_back(UPGRADE_FACTORY);

        actions.push_back(BUY_NEXT);
        for (int i = 0; i < 10; i++) {
            actions.push_back(BUY_SAME);
            actions.push_back(NOTHING);
        }

        actions.push_back(UPGRADE_FACTORY);
        actions.push_back(UPGRADE_FACTORY);
        actions.push_back(UPGRADE_FACTORY);

        while (actions.size() < OPERATION_LENGTH) {
            actions.push_back(NOTHING);
        }

        assert(actions.size() == OPERATION_LENGTH);

        return actions;
    }

    vector <string> run(string events) {
        init(events);

        vector<int> bestActions = firstAnswer();
        vector<int> actions = bestActions;
        ll bestScore = updateAnswer(bestActions);
        ll currentScore = bestScore;

        int opes[2] = {BUY_SAME, UPGRADE_FACTORY};
        int tryCount = 0;
        int R = 500000;
        double k = 10.0;
        double currentTime = getTime(startCycle);
        double remainTime = 0.0;

        while (currentTime < TIME_LIMIT) {
            currentTime = getTime(startCycle);
            remainTime = (TIME_LIMIT - currentTime) / TIME_LIMIT;

            int j = xor128() % OPERATION_LENGTH;
            int act = actions[j];

            if (actions[j] == NOTHING) {
                actions[j] = opes[xor128() % 2];
            } else if (actions[j] == BUY_SAME) {
                actions[j] = (xor128() % 2 == 0) ? NOTHING : UPGRADE_FACTORY;
            } else if (actions[j] == UPGRADE_FACTORY) {
                actions[j] = (xor128() % 2 == 0) ? NOTHING : BUY_SAME;
            } else {
                continue;
            }

            ll score = updateAnswer(actions);
            ll diff = currentScore - score;

            if (currentScore < score || (xor128() % R < R * exp(-diff / (k * sqrt(remainTime))))) {
                currentScore = score;

                if (bestScore < score) {
                    cerr << bestScore << endl;
                    bestScore = score;
                    bestActions = actions;
                }
            } else {
                actions[j] = act;
            }
            tryCount++;
        }

        fprintf(stderr, "tryCount = %d\n", tryCount);
        updateAnswer(bestActions);
        vector <string> answer = createAnswer();

        return answer;
    }

    vector <string> createAnswer() {
        vector <string> answer;

        for (int i = 0; i < N; i++) {
            switch (operations[i]) {
                case NOTHING:
                    answer.push_back("nothing");
                    break;
                case CLICK:
                    answer.push_back("click");
                    break;
                case BUY:
                    answer.push_back("buy");
                    break;
                case SELL:
                    break;
                case REINFORCE:
                    break;
                case ENHCLICK:
                    answer.push_back("enhclick");
                    break;
                case BUY_HAND:
                    answer.push_back("buy hand");
                    break;
                case BUY_LILY:
                    answer.push_back("buy lily");
                    break;
                case BUY_FACTORY:
                    answer.push_back("buy factory");
                    break;
                case BUY_CASINO:
                    answer.push_back("buy casino");
                    break;
                case BUY_GRIMOIRE:
                    answer.push_back("buy grimoire");
                    break;
                case UPDATE_HAND:
                    answer.push_back("reinforce hand");
                    break;
                case UPDATE_LILY:
                    answer.push_back("reinforce lily");
                    break;
                case UPDATE_FACTORY:
                    answer.push_back("reinforce factory");
                    break;
                case UPDATE_CASINO:
                    answer.push_back("reinforce casino");
                    break;
                case UPDATE_GRIMOIRE:
                    answer.push_back("reinforce grimoire");
                    break;
                case SELL_HAND:
                    answer.push_back("sell hand");
                    break;
                case SELL_LILY:
                    answer.push_back("sell lily");
                    break;
                default:
                    cerr << operations[i] << endl;
                    assert(false);
            }
        }

        return answer;
    }

    ll updateAnswer(vector<int> actions) {
        memset(operations, CLICK, sizeof(operations));

        int index = 0;
        int clickLevel = 0;
        int factoryGrade = 0;
        ll cookie = 0;
        ll productivity = 0;
        int clickPower = 1;
        ll updateCost;
        int clickPoint;
        ll price;
        int factoryCount[7] = {0, 0, 0, 0, 0, 0, 0};
        int factoryLevels[7] = {0, 0, 0, 0, 0, 0, 0};
        int nextFactory;
        int sell_price;

        for (int i = 0; i < N; i++) {
            if (actions.size() <= index) break;

            clickPoint = clickPower;

            switch (actions[index]) {
                case ENHCLICK:
                    updateCost = UPDATE_COST[CLICK][clickLevel];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        clickLevel++;
                        clickPower *= 2;
                        operations[i] = ENHCLICK;
                        index++;
                        clickPoint = 0;
                    }
                    break;
                case BUY_LILY:
                    price = factory_price[LILY][factoryCount[LILY]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    if (cookie >= price) {
                        cookie -= price;
                        factoryCount[LILY]++;
                        productivity += PRODUCTIVITY[LILY];
                        operations[i] = BUY_LILY;
                        factoryGrade = max(factoryGrade, LILY);
                        index++;
                        clickPoint = 0;
                    }
                    break;
                case BUY_NEXT:
                    nextFactory = factoryGrade + 1;

                    if (nextFactory <= GRIMOIRE) {
                        price = factory_price[nextFactory][factoryCount[nextFactory]];
                        if (bonus[i] == SALE) {
                            price = ceil(price * 0.9) + 1;
                        }

                        if (cookie >= price) {
                            cookie -= price;
                            factoryCount[nextFactory]++;
                            productivity += PRODUCTIVITY[nextFactory];
                            operations[i] = BUY_OPERATIONS[nextFactory];
                            factoryGrade = max(factoryGrade, nextFactory);
                            index++;
                            clickPoint = 0;
                        }
                    } else {
                        index++;
                    }
                    break;
                case BUY_SAME:
                    price = factory_price[factoryGrade][factoryCount[factoryGrade]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    if (cookie >= price) {
                        cookie -= price;
                        factoryCount[factoryGrade]++;
                        productivity += PRODUCTIVITY[factoryGrade] * pow(2, factoryLevels[factoryGrade]);
                        operations[i] = BUY_OPERATIONS[factoryGrade];
                        index++;
                        clickPoint = 0;
                    }
                    break;
                case UPGRADE_FACTORY:
                    updateCost = update_cost[factoryGrade][factoryLevels[factoryGrade]];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    assert(factoryCount[factoryGrade] > 0);

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        productivity += factoryCount[factoryGrade] * PRODUCTIVITY[factoryGrade] *
                                        pow(2, factoryLevels[factoryGrade]);
                        operations[i] = UPDATE_OPERATIONS[factoryGrade];
                        index++;
                        factoryLevels[factoryGrade]++;
                        clickPoint = 0;
                    }
                    break;
                case SELL_SAME:
                    assert(factoryCount[factoryGrade] > 0);
                    nextFactory = factoryGrade + 1;

                    sell_price = 0.25 * factory_price[factoryGrade][factoryCount[factoryGrade] - 1];

                    if (nextFactory <= GRIMOIRE) {
                        if (sell_price + cookie >= factory_price[nextFactory][0]) {
                            cookie += sell_price;
                            productivity -= PRODUCTIVITY[factoryGrade] * pow(2, factoryLevels[factoryGrade]);
                            operations[i] = SELL_OPERATIONS[factoryGrade];
                            index++;
                            factoryCount[factoryGrade]--;
                            clickPoint = 0;
                        }
                    }
                    break;
                case NOTHING:
                    index++;
                    break;
                default:
                    assert(false);
                    break;
            }

            switch (bonus[i]) {
                case FEVER:
                    cookie += 7 * (productivity + clickPoint);
                    break;
                case BONUS:
                    cookie += productivity + clickPoint;
                    cookie += ceil(cookie * 0.01) - 1;
                    break;
                default:
                    cookie += productivity + clickPoint;
                    break;
            }
        }

        return cookie;
    }

    ll calcScore() {
        ll cookie = 0;
        int clickPower = 1;
        int clickLevel = 0;
        int updateCost;
        int price;
        int factoryCount[6] = {0, 0, 0, 0, 0, 0};
        int factoryLevels[6] = {0, 0, 0, 0, 0, 0};
        int factoryLevel = 0;
        int productivity = 0;
        int sell_price;

        for (int i = 0; i < N; i++) {
            switch (operations[i]) {
                case NOTHING:
                    break;
                case CLICK:
                    if (bonus[i] == FEVER) {
                        cookie += 7 * clickPower;
                    } else {
                        cookie += clickPower;
                    }
                    break;
                case ENHCLICK:
                    updateCost = UPDATE_COST[CLICK][clickLevel];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    assert(cookie >= updateCost);

                    cookie -= updateCost;
                    clickPower *= 2;
                    clickLevel++;
                    break;
                case BUY_HAND:
                    price = factory_price[HAND][factoryCount[HAND]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    assert(cookie >= price);

                    cookie -= price;
                    factoryLevel = max(factoryLevel, HAND);
                    factoryCount[HAND]++;
                    productivity += PRODUCTIVITY[HAND] * pow(2, factoryLevels[HAND]);
                    break;
                case BUY_LILY:
                    price = factory_price[LILY][factoryCount[LILY]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    assert(cookie >= price);

                    cookie -= price;
                    factoryLevel = max(factoryLevel, LILY);
                    factoryCount[LILY]++;
                    productivity += PRODUCTIVITY[LILY] * pow(2, factoryLevels[LILY]);
                    break;
                case BUY_FACTORY:
                    price = factory_price[FACTORY][factoryCount[FACTORY]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    assert(cookie >= price);

                    cookie -= price;
                    factoryCount[FACTORY]++;
                    productivity += PRODUCTIVITY[FACTORY] * pow(2, factoryLevels[FACTORY]);
                    break;
                case BUY_CASINO:
                    price = factory_price[CASINO][factoryCount[CASINO]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    assert(cookie >= price);

                    cookie -= price;
                    factoryCount[CASINO]++;
                    productivity += PRODUCTIVITY[CASINO] * pow(2, factoryLevels[CASINO]);
                    break;
                case BUY_GRIMOIRE:
                    price = factory_price[GRIMOIRE][factoryCount[GRIMOIRE]];
                    if (bonus[i] == SALE) {
                        price = ceil(price * 0.9) + 1;
                    }

                    assert(cookie >= price);

                    cookie -= price;
                    factoryCount[GRIMOIRE]++;
                    productivity += PRODUCTIVITY[GRIMOIRE] * pow(2, factoryLevels[GRIMOIRE]);
                    break;
                case UPDATE_HAND:
                    updateCost = update_cost[HAND][factoryLevels[HAND]];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        productivity += factoryCount[HAND] * PRODUCTIVITY[HAND] * pow(2, factoryLevels[HAND]);
                        factoryLevels[HAND]++;
                    }
                    break;
                case UPDATE_LILY:
                    updateCost = update_cost[LILY][factoryLevels[LILY]];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        productivity += factoryCount[LILY] * PRODUCTIVITY[LILY] * pow(2, factoryLevels[LILY]);
                        factoryLevels[LILY]++;
                    }
                    break;
                case UPDATE_FACTORY:
                    updateCost = update_cost[FACTORY][factoryLevels[FACTORY]];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        productivity += factoryCount[FACTORY] * PRODUCTIVITY[FACTORY] * pow(2, factoryLevels[FACTORY]);
                        factoryLevels[FACTORY]++;
                    }
                    break;
                case UPDATE_CASINO:
                    updateCost = update_cost[CASINO][factoryLevels[CASINO]];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        productivity += factoryCount[CASINO] * PRODUCTIVITY[CASINO] * pow(2, factoryLevels[CASINO]);
                        factoryLevels[CASINO]++;
                    }
                    break;
                case UPDATE_GRIMOIRE:
                    updateCost = update_cost[GRIMOIRE][factoryLevels[GRIMOIRE]];
                    if (bonus[i] == SALE) {
                        updateCost = ceil(updateCost * 0.9) + 1;
                    }

                    if (cookie >= updateCost) {
                        cookie -= updateCost;
                        productivity +=
                                factoryCount[GRIMOIRE] * PRODUCTIVITY[GRIMOIRE] * pow(2, factoryLevels[GRIMOIRE]);
                        factoryLevels[GRIMOIRE]++;
                    }
                    break;
                case SELL_HAND:
                    assert(factoryCount[HAND] > 0);
                    sell_price = 0.25 * factory_price[HAND][factoryCount[HAND] - 1];

                    if (sell_price + cookie >= factory_price[LILY][0]) {
                        cookie += sell_price;
                        productivity -= PRODUCTIVITY[HAND] * pow(2, factoryLevels[HAND]);
                        factoryCount[HAND]--;
                    }
                    break;
                case SELL_LILY:
                    assert(factoryCount[LILY] > 0);
                    sell_price = 0.25 * factory_price[LILY][factoryCount[LILY] - 1];

                    if (sell_price + cookie >= factory_price[FACTORY][0]) {
                        cookie += sell_price;
                        productivity -= PRODUCTIVITY[LILY] * pow(2, factoryLevels[LILY]);
                        factoryCount[LILY]--;
                    }
                    break;
                default:
                    assert(false);
                    break;
            }

            switch (bonus[i]) {
                case FEVER:
                    cookie += 7 * productivity;
                    break;
                case BONUS:
                    cookie += productivity;
                    cookie += ceil(cookie * 0.01);
                    break;
                default:
                    cookie += productivity;
                    break;
            }

            // fprintf(stderr, "%d: cookie = %d\n", i, cookie);
        }

        fprintf(stderr, "clickLevel = %d\n", clickLevel);

        return cookie;
    }
};

int main() {
    int n;
    string s, res;
    CookieClicker cc;

    cin >> n;
    cin >> s;

    vector <string> answer = cc.run(s);

    for (int i = 0; i < N; i++) {
        cout << answer[i] << endl;
        cin >> res;
        assert(res[0] == 'o');
    }

    ll score = cc.calcScore();
    fprintf(stderr, "Score = %lld\n", score);

    return 0;
}
0