結果

問題 No.5003 物理好きクリッカー
ユーザー maimai
提出日時 2018-12-04 15:54:09
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 41 ms / 10,000 ms
コード長 13,817 bytes
コンパイル時間 2,695 ms
実行使用メモリ 21,996 KB
スコア 32,202,976,554
平均クエリ数 10000.00
最終ジャッジ日時 2021-07-19 08:28:09
合計ジャッジ時間 6,225 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 37 ms
21,384 KB
testcase_01 AC 38 ms
21,384 KB
testcase_02 AC 38 ms
21,600 KB
testcase_03 AC 39 ms
21,864 KB
testcase_04 AC 38 ms
21,348 KB
testcase_05 AC 37 ms
21,516 KB
testcase_06 AC 36 ms
21,300 KB
testcase_07 AC 37 ms
21,360 KB
testcase_08 AC 37 ms
21,528 KB
testcase_09 AC 36 ms
21,804 KB
testcase_10 AC 37 ms
21,804 KB
testcase_11 AC 37 ms
21,360 KB
testcase_12 AC 41 ms
21,384 KB
testcase_13 AC 36 ms
21,828 KB
testcase_14 AC 37 ms
21,504 KB
testcase_15 AC 36 ms
21,540 KB
testcase_16 AC 36 ms
21,360 KB
testcase_17 AC 37 ms
21,384 KB
testcase_18 AC 35 ms
21,696 KB
testcase_19 AC 38 ms
21,816 KB
testcase_20 AC 37 ms
21,840 KB
testcase_21 AC 38 ms
21,864 KB
testcase_22 AC 37 ms
21,780 KB
testcase_23 AC 38 ms
21,852 KB
testcase_24 AC 38 ms
21,480 KB
testcase_25 AC 37 ms
21,516 KB
testcase_26 AC 38 ms
21,792 KB
testcase_27 AC 38 ms
21,504 KB
testcase_28 AC 38 ms
21,864 KB
testcase_29 AC 39 ms
21,348 KB
testcase_30 AC 38 ms
21,372 KB
testcase_31 AC 37 ms
21,864 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: 関数 ‘char* machineToString(EMachine)’ 内:
main.cpp:80:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   80 |         "hand",
      |         ^~~~~~
main.cpp:81:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   81 |         "lily",
      |         ^~~~~~
main.cpp:82:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   82 |         "factory",
      |         ^~~~~~~~~
main.cpp:83:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   83 |         "casino",
      |         ^~~~~~~~
main.cpp:84:9: 警告: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
   84 |         "grimoire"
      |         ^~~~~~~~~~

ソースコード

diff #

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

using namespace std;
using ll = long long int;

#define debugos cout
#define debug(v) {printf("L%d %s > ",__LINE__,#v);debugos<<(v)<<endl;}
#define debugv(v) {printf("L%d %s > ",__LINE__,#v);for(auto e:(v)){debugos<<e<<" ";}debugos<<endl;}
#define debuga(m,w) {printf("L%d %s > ",__LINE__,#m);for(int x=0;x<(w);x++){debugos<<(m)[x]<<" ";}debugos<<endl;}
#define debugaa(m,h,w) {printf("L%d %s >\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){debugos<<(m)[y][x]<<" ";}debugos<<endl;}}
#define ALL(v) (v).begin(),(v).end()
#define repeat(cnt,l) for(auto cnt=decltype(l)();(cnt)<(l);++(cnt))
#define rrepeat(cnt,l) for(auto cnt=(l)-1;0<=(cnt);--(cnt))
#define iterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);++(cnt))
#define diterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);--(cnt))
const ll MD = 1000000007ll; const long double PI = 3.1415926535897932384626433832795L;
inline void assert_call(bool assertion, function<void()> f) { if (!assertion) { cerr << "assertion fault:" << endl; f(); abort(); } }
template<typename T1, typename T2> inline ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << '(' << p.first << ':' << p.second << ')'; return o; }
template<typename Vec> inline ostream& _ostream_vecprint(ostream& os, const Vec& a) {
    os << '['; for (const auto& e : a) os << ' ' << e << ' '; os << ']'; return os;
}
template<typename T> inline ostream& operator<<(ostream& o, const vector<T>& v) { return _ostream_vecprint(o, v); }
template<typename T, size_t S> inline ostream& operator<<(ostream& o, const array<T, S>& v) { return _ostream_vecprint(o, v); }
template<typename T> inline T& chmax(T& to, const T& val) { return to = max(to, val); }
template<typename T> inline T& chmin(T& to, const T& val) { return to = min(to, val); }
void bye(string s, int code = 0) { cout << s << endl; exit(code); }
mt19937_64 randdev(8901016);
template<typename T, typename Random = decltype(randdev), typename enable_if<is_integral<T>::value>::type* = nullptr>
inline T rand(T l, T h, Random& rand = randdev) { return uniform_int_distribution<T>(l, h)(rand); }
template<typename T, typename Random = decltype(randdev), typename enable_if<is_floating_point<T>::value>::type* = nullptr>
inline T rand(T l, T h, Random& rand = randdev) { return uniform_real_distribution<T>(l, h)(rand); }


// 

template<typename T1, typename T2>
struct Tag {

    T1 first; T2 second;

    Tag(T1 t1, T2 t2) :first(t1), second(t2) {}
    Tag(const pair<T1, T2>& p) :first(p.first), second(p.second) { }
    Tag(const pair<T1, T2>&& p) :first(p.first), second(p.second) { }

    inline bool operator == (const Tag& t) const {
        return first == t.first;
    }
    inline bool operator <(const Tag& t) const {
        return first < t.first;
    }
};


//


enum EMachine {
    kHand = 0, kLily, kFactory, kCasino, kGrimoire, kClicker
};

enum ECommand {
    kClick = 0,
    kBuy,
    kReinforce,
    kSell
};

enum EEffect {
    kNothing = 0,
    kBonus,
    kFever,
    kSale
};


inline char* machineToString(EMachine m) {
    static char* s[] = {
        "hand",
        "lily",
        "factory",
        "casino",
        "grimoire"
    };
    return s[(int)m];
}


inline EEffect charToEffect(char c) {
    return
        c == 'N' ? EEffect::kNothing :
        c == 'B' ? EEffect::kBonus :
        c == 'F' ? EEffect::kFever :
        c == 'S' ? EEffect::kSale : EEffect::kNothing;
}


//


struct Action {
    ECommand command;
    EMachine target;
    Action(ECommand aCommand = ECommand::kClick, EMachine aTarget = EMachine::kHand)
        :command(aCommand), target(aTarget) {
    }

    void print() const {
        switch (command)
        {
        case kClick:
            cout << "click" << endl;
            break;
        case kBuy:
            cout << "buy " << machineToString(target) << endl;
            break;
        case kReinforce:
            if (target == EMachine::kClicker)
                cout << "enhclick" << endl;
            else
                cout << "reinforce " << machineToString(target) << endl;
            break;
        case kSell:
            cout << "sell " << machineToString(target) << endl;
            break;
        default:
            clog << "invalid command\n";
            break;
        }
    }
};


class State {

    ll wallet_;
    array<int, 6> numMachine_;
    array<int, 6> lvlMachine_;
    array<ll, 5> costBuyMachine_ = { 150ll, 2000ll, 30000ll, 600000ll, 10000000ll };
    array<ll, 6> costRfMachine_ = { 1500ll, 20000ll, 300000ll, 6000000ll, 100000000ll, 15ll };

public:

    State() :wallet_(0) {
        numMachine_.fill(0);
        numMachine_[5] = 1;
        lvlMachine_.fill(0);
    }

    static ll discount(ll cost) noexcept {
        return (cost * 9 + 9) / 10;
    }

    //
    inline ll costBuyMachine(EMachine e) const {
        return costBuyMachine_[(int)e];
    }
    inline ll costReinforceMachine(EMachine e) const {
        return costRfMachine_[(int)e];
    }
    inline ll wallet() const {
        return wallet_;
    }
    inline int countOfMachine(EMachine e) const {
        return numMachine_[(int)e];
    }

    //
    inline bool buyableMachine(EMachine e, bool sale = false) const {
        return sale ?
            discount(costBuyMachine_[(int)e]) <= wallet_ :
            costBuyMachine_[(int)e] <= wallet_;
    }
    inline bool reinforceableMachine(EMachine e, bool sale = false) const {
        return sale ?
            discount(costRfMachine_[(int)e]) <= wallet_ :
            costRfMachine_[(int)e] <= wallet_;
    }

    //
    inline ll efficiency(EMachine e) const {
        const ll s[] = { 1, 10, 120, 2000, 25000, 1 };
        return s[(int)e] * (1ll << lvlMachine_[(int)e])*numMachine_[(int)e];
    }
    inline ll nextLevelEfficiency(EMachine e) const {
        const ll s[] = { 1, 10, 120, 2000, 25000, 1 };
        return s[(int)e] * (1ll << (lvlMachine_[(int)e] + 1))*numMachine_[(int)e];
    }
    inline ll oneMoreEfficiency(EMachine e) const {
        const ll s[] = { 1, 10, 120, 2000, 25000, 1 };
        return s[(int)e] * (1ll << lvlMachine_[(int)e])*(numMachine_[(int)e] + 1);
    }

    void applyAction(Action act, EEffect eff) {
        if (act.command == ECommand::kClick) {
        }
        else if (act.command == ECommand::kBuy) {
            numMachine_[act.target] += 1;
            wallet_ -= eff == EEffect::kSale ? discount(costBuyMachine_[act.target]) : costBuyMachine_[act.target];
            costBuyMachine_[act.target] = (costBuyMachine_[act.target] * 6 + 4) / 5;
        }
        else if (act.command == ECommand::kReinforce) {
            lvlMachine_[act.target] += 1;
            wallet_ -= eff == EEffect::kSale ? discount(costRfMachine_[act.target]) : costRfMachine_[act.target];
            costRfMachine_[act.target] = (costRfMachine_[act.target] * 10);
        }
        else if (act.command == ECommand::kSell) {
            numMachine_[act.target] -= 1;
            costBuyMachine_[act.target] = (costBuyMachine_[act.target] * 5) / 6;
            wallet_ += (costBuyMachine_[act.target]+3)/4;
        }

        assert(wallet_ >= 0);
        ll fever = eff == EEffect::kFever ? 7 : 1;
        for (int i = 4 + (act.command == ECommand::kClick); i >= 0; --i) {
            wallet_ += efficiency((EMachine)i);
        }

        if (eff == EEffect::kBonus) {
            wallet_ += (wallet_ + 99) / 100;
        }
    }

    void dumplog() {
        clog << "money: " << wallet_ << '\n';
        clog << "nMachine" << numMachine_ << '\n';
        clog << "lMachine" << lvlMachine_ << '\n';
        clog << "buycost" << costBuyMachine_ << '\n';
        clog << "rfcost" << costRfMachine_ << '\n';
        clog << "efficiency:";
        repeat(i, 6) clog << efficiency(EMachine(i)) << " ";
        clog << '\n';
    }

};


//


namespace IN {
    const int maxTurnCount = 10000;
    EEffect effects[maxTurnCount];
    bool isGenerated = false;
}


//


void convertinput(const string& l) {

    using namespace IN;
    int fever = 0;
    int sale = 0;
    repeat(i, maxTurnCount) {
        auto e = charToEffect(l[i]);
        effects[i] = e == EEffect::kBonus ? EEffect::kBonus : EEffect::kNothing;
        if (fever > 0) {
            --fever;
            effects[i] = EEffect::kFever;
        }
        if (sale > 0) {
            --sale;
            effects[i] = EEffect::kSale;
        }
        if (e == EEffect::kFever) {
            fever = 20;
        }
        else if (e == EEffect::kSale) {
            sale = 1;
        }
    }
}


void generateInput() {
    using namespace IN;

    string l; l.reserve(maxTurnCount);
    int next = rand(0, 200);
    repeat(i, maxTurnCount) {
        if (next > 0) {
            --next;
            l.push_back('N');
        }
        else {
            l.push_back("DFS"[rand(0, 2)]);
            next = rand(100, 200);
        }
    }
    convertinput(l);
    isGenerated = true;
}


void scan() {
    using namespace IN;
    int n;
    cin >> n;
    if (maxTurnCount != n) {
        generateInput();
        return;
    }
    string l;
    cin >> l;

    convertinput(l);
}


//


namespace Solver {


    void renda(State& state, int currentTurnCount, bool echo = false) {
        int num = 0;
        repeat(m, 5) num += state.countOfMachine(EMachine(m));

        for (; currentTurnCount < IN::maxTurnCount-num; ++currentTurnCount) {
            state.applyAction(Action(ECommand::kClick), IN::effects[currentTurnCount]);
            if (echo) Action(ECommand::kClick).print();
        }
        for (; currentTurnCount < IN::maxTurnCount; ++currentTurnCount) {
            repeat(m, 5) {
                if (state.countOfMachine(EMachine(m)) > 0) {
                    state.applyAction(Action(ECommand::kSell, EMachine(m)), IN::effects[currentTurnCount]);
                    if (echo) Action(ECommand::kSell, EMachine(m)).print();
                    break;
                }
            }
        }
    }


    void solve() {

        State state;

        array<Action, IN::maxTurnCount> stackedActions;
        pair<ll, int> bestWalletTurn(0, 0);

        repeat(turncount, IN::maxTurnCount) {
            const EEffect effect = IN::effects[turncount];

            // Action action(ECommand::kClick);

            Tag<ll, Action> best(0, ECommand::kClick);

            auto topMachineI = 0;
            rrepeat(mm, 5) {
                if (state.countOfMachine((EMachine)mm) > 0) {
                    topMachineI = mm;
                    break;
                }
            }

            repeat(mm, 5) {
                EMachine m = (EMachine)mm;
                if (mm == topMachineI || mm == topMachineI+1)  {
                    if (state.buyableMachine(m, effect == EEffect::kSale)) {
                        chmax(best, Tag<ll, Action>(
                            state.oneMoreEfficiency(m) - state.efficiency(m),
                            Action(ECommand::kBuy, m)
                            ));
                    }
                }
                if (state.countOfMachine(m) > 0) {
                    if (state.reinforceableMachine(m, effect == EEffect::kSale)) {
                        chmax(best, Tag<ll, Action>(
                            state.nextLevelEfficiency(m) - state.efficiency(m),
                            Action(ECommand::kReinforce, m)
                            ));
                    }
                }
            }
            // rrepeat(mm, 4) {
            //     EMachine m = (EMachine)mm;
            //     if (state.countOfMachine(m) > 0 && mm < topMachineI-3) {
            //         chmax(best, Tag<ll, Action>(
            //             1e18,
            //             Action(ECommand::kSell, m)
            //             ));
            //     }
            // }

            if (state.reinforceableMachine(EMachine::kClicker, effect == EEffect::kSale)) {
                chmax(best, Tag<ll, Action>(
                    state.nextLevelEfficiency(EMachine::kClicker) - state.efficiency(EMachine::kClicker),
                    Action(ECommand::kReinforce, EMachine::kClicker)
                    ));
            }

            if (turncount > IN::maxTurnCount * 2 / 3 && best.second.command != ECommand::kClick) {
                State s = state;
                renda(s, turncount);
                chmax(bestWalletTurn, make_pair(s.wallet(), turncount));
            }

            // action.print();
            stackedActions[turncount] = best.second;
            state.applyAction(best.second, effect);
        }

        if (!IN::isGenerated) {
            state = State();
            repeat(i, bestWalletTurn.second) {
                state.applyAction(stackedActions[i], IN::effects[i]);
                stackedActions[i].print();
            }
            renda(state, bestWalletTurn.second, true);
        }
        else {
            clog << "## result" << endl;
            state = State();
            repeat(i, bestWalletTurn.second) {
                state.applyAction(stackedActions[i], IN::effects[i]);
                if (stackedActions[i].command != ECommand::kClick)
                    stackedActions[i].print();
            }
            clog << "-- before selling --" << endl;
            state.dumplog();
            renda(state, bestWalletTurn.second);
            clog << "-- final -- " << endl;
            state.dumplog();
            clog << "BEST:" << (double)bestWalletTurn.first << endl;
            clog << "bestWalletTurn: " << bestWalletTurn.second << endl;
        }
    }

}


int main() {
    using namespace IN;

    scan();

    Solver::solve();

    if (!isGenerated) {
        repeat(i, maxTurnCount) {
            string str;
            cin >> str;
            assert(str == "ok");
        }
    }

    return 0;
}
0