結果
| 問題 |
No.5018 Let's Make a Best-seller Book
|
| コンテスト | |
| ユーザー |
e869120
|
| 提出日時 | 2023-09-18 17:21:31 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 38 ms / 400 ms |
| コード長 | 6,801 bytes |
| コンパイル時間 | 796 ms |
| コンパイル使用メモリ | 82,716 KB |
| 実行使用メモリ | 24,396 KB |
| スコア | 132,305 |
| 平均クエリ数 | 52.00 |
| 最終ジャッジ日時 | 2023-10-01 12:31:01 |
| 合計ジャッジ時間 | 9,393 ms |
|
ジャッジサーバーID (参考情報) |
judge15 / judge13 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 100 |
ソースコード
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
// =============================================================== デバッグ用の出力 ===============================================================
class DebugMode {
public:
int T = 52;
int N = 10;
int CurrentTurn;
int CurrentMoney;
int Score;
vector<int> Sales;
vector<int> Remain;
vector<int> Popula;
vector<double> D;
vector<vector<double>> Z;
double Randouble() {
double s = 1, t = 0;
for (int i = 0; i < 3; i++) {
s /= 1024.0;
t += 1.0 * (rand() % 1024) * s;
}
return t;
}
void Initialize() {
CurrentMoney = 2000000;
CurrentTurn = 0;
Score = 0;
Sales = vector<int>(N, 0);
Remain = vector<int>(N, 0);
Popula = vector<int>(N, 0);
D = vector<double>(N, 0);
Z = vector<vector<double>>(T, vector<double>(N, 0));
for (int i = 0; i < N; i++) D[i] = Randouble() * 1.0 + 0.5;
for (int i = 0; i < T; i++) {
for (int j = 0; j < N; j++) Z[i][j] = Randouble() * 0.5 + 0.75;
}
}
void Refresh() {
int i = CurrentTurn;
for (int j = 0; j < N; j++) Sales[j] = min(Remain[j], (int)(1.0 * pow(Remain[j], 0.5) * pow(1.05, Popula[j]) * D[j] * Z[i][j]));
for (int j = 0; j < N; j++) {
if (10 * Sales[j] >= 3 * Remain[j]) Popula[j] = min(+60, Popula[j] + 1);
if (10 * Sales[j] < 1 * Remain[j]) Popula[j] = max(-60, Popula[j] - 1);
}
for (int j = 0; j < N; j++) Score += Sales[j];
for (int j = 0; j < N; j++) CurrentMoney += 1000LL * Sales[j];
for (int j = 0; j < N; j++) Remain[j] -= Sales[j];
CurrentTurn += 1;
}
};
// =============================================================== デバッグ用の出力 ===============================================================
const int DEBUG = 1;
int T, N;
int Money;
int S[19], P[19], R[19];
int Prev_Ad;
double Expected_D[19], Sum_D[19], Cnt_D[19];
DebugMode COMP;
void Initialize() {
T = 0; N = 0; Money = 0; Prev_Ad = 0;
for (int i = 0; i < 19; i++) {
Expected_D[i] = 0; Sum_D[i] = 0; Cnt_D[i] = 0;
S[i] = 0; P[i] = 0; R[i] = 0;
}
}
void Ask(int Type, vector<int> vec) {
if (DEBUG == 1) {
cout << Type;
for (int i = 0; i < vec.size(); i++) cout << " " << vec[i];
cout << endl;
}
if (DEBUG == 2 && Type == 1) {
for (int i = 0; i < N; i++) COMP.CurrentMoney -= 500 * vec[i];
for (int i = 0; i < N; i++) COMP.Remain[i] += vec[i];
}
if (DEBUG == 2 && Type == 2) {
COMP.CurrentMoney -= 500000 * (1 << (vec[0] - 1));
for (int i = 0; i < N; i++) COMP.Popula[i] = min(60, COMP.Popula[i] + vec[0]);
}
}
void Decide(int turn) {
bool AdFlag = false;
int count60 = 0;
for (int i = 1; i <= N; i++) {
if (P[i] == 60) count60 += 1;
}
// 広告を打つ条件
if (turn == 1) AdFlag = true;
if (turn <= 15 && (Money >= 1100000 && turn - Prev_Ad >= 2 && count60 <= 3)) AdFlag = true;
if (turn <= 25 && (Money >= 1300000 && turn - Prev_Ad >= 2 && count60 <= 3)) AdFlag = true;
if (turn <= 60 && (Money >= 1500000 && turn - Prev_Ad >= 2 && count60 <= 3)) AdFlag = true;
// 広告を打つ場合
if (AdFlag == true) {
Ask(2, vector<int>{2});
Prev_Ad = turn;
}
// 広告を打たない場合
else {
vector<int> L(N, 0);
int NeedMoney = 0;
for (int i = 1; i <= N; i++) {
double keisuu = 5.0;
if (P[i] >= 40) keisuu = 10.0;
if (P[i] >= 50) keisuu = 70.0;
int Goal = keisuu * pow(1.05, 1.0 * P[i]) * Expected_D[i] * pow(1.05, 1.0 * P[i]);
Goal = max(1, Goal - R[i]);
L[i - 1] = Goal;
NeedMoney += 500 * Goal;
}
if (NeedMoney > Money) {
for (int i = 1; i <= N; i++) L[i - 1] = (1LL * L[i - 1] * Money / NeedMoney);
}
Ask(1, L);
}
}
int main() {
// ========================================================================= 通常モード =========================================================================
if (DEBUG == 1) {
cin >> T >> N >> Money;
for (int i = 1; i <= N; i++) Expected_D[i] = 1.0;
// インタラクティブ開始
for (int t = 1; t <= T; t++) {
// (あ) 行動を決める
Decide(t);
// (い) 売上部数などを入力する
cin >> Money;
for (int i = 1; i <= N; i++) cin >> S[i];
for (int i = 1; i <= N; i++) cin >> P[i];
for (int i = 1; i <= N; i++) cin >> R[i];
cerr << "Turn = " << t << ":" << endl;
cerr << Money << endl;
for (int i = 1; i <= N; i++) cerr << S[i] << " "; cerr << endl;
for (int i = 1; i <= N; i++) cerr << P[i] << " "; cerr << endl;
for (int i = 1; i <= N; i++) cerr << R[i] << " "; cerr << endl;
cerr << endl;
// D の値を更新
for (int i = 1; i <= N; i++) {
if (S[i] == 0) continue;
int moto_popular = P[i];
if (10 * S[i] >= 3 * (S[i] + R[i])) moto_popular -= 1;
if (10 * S[i] < 1 * (S[i] + R[i])) moto_popular += 1;
double expected = (0.5 + S[i]) / (pow(1.0 * (S[i] + R[i]), 0.5) * pow(1.05, moto_popular));
Sum_D[i] += expected;
Cnt_D[i] += 1.0;
Expected_D[i] = min(1.45, max(0.55, Sum_D[i] / Cnt_D[i]));
}
}
}
// ========================================================================= デバッグモード =========================================================================
if (DEBUG == 2) {
int NumCases = 50;
int ScoreSum = 0;
int ScoreCnt = 0;
for (int cases = 1; cases <= NumCases; cases++) {
Initialize();
T = 52; N = 10; Money = 2000000; COMP.Initialize();
for (int i = 1; i <= N; i++) Expected_D[i] = 1.0;
// インタラクティブ開始
for (int t = 1; t <= T; t++) {
// (あ) 行動を決める
Decide(t);
// (い) 売上部数などを入力する
COMP.Refresh();
Money = COMP.CurrentMoney;
for (int i = 1; i <= N; i++) S[i] = COMP.Sales[i - 1];
for (int i = 1; i <= N; i++) P[i] = COMP.Popula[i - 1];
for (int i = 1; i <= N; i++) R[i] = COMP.Remain[i - 1];
if (NumCases == 1) {
cerr << "Turn = " << t << ":" << endl;
cerr << Money << endl;
for (int i = 1; i <= N; i++) cerr << S[i] << " "; cerr << endl;
for (int i = 1; i <= N; i++) cerr << P[i] << " "; cerr << endl;
for (int i = 1; i <= N; i++) cerr << R[i] << " "; cerr << endl;
cerr << endl;
}
// D の値を更新
for (int i = 1; i <= N; i++) {
if (S[i] == 0) continue;
int moto_popular = P[i];
if (10 * S[i] >= 3 * (S[i] + R[i])) moto_popular -= 1;
if (10 * S[i] < 1 * (S[i] + R[i])) moto_popular += 1;
double expected = (0.5 + S[i]) / (pow(1.0 * (S[i] + R[i]), 0.5) * pow(1.05, moto_popular));
Sum_D[i] += expected;
Cnt_D[i] += 1.0;
Expected_D[i] = min(1.45, max(0.55, Sum_D[i] / Cnt_D[i]));
}
}
printf("Case#% 3d: Score =% 7d\n", cases, COMP.Score);
ScoreSum += COMP.Score;
ScoreCnt += 1;
}
printf("=======================================\n");
printf("Average Score =% 9d\n", ScoreSum / ScoreCnt);
}
return 0;
}
e869120