結果
| 問題 |
No.162 8020運動
|
| コンテスト | |
| ユーザー |
mayoko_
|
| 提出日時 | 2015-03-08 20:18:33 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 172 ms / 5,000 ms |
| コード長 | 1,925 bytes |
| コンパイル時間 | 843 ms |
| コンパイル使用メモリ | 76,776 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-06-24 16:26:16 |
| 合計ジャッジ時間 | 4,307 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 26 |
ソースコード
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <utility>
#include <set>
#include <cctype>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long ll;
double memo[25][20]; // memo[Y][R]はあとY年残ってる時R本の歯が連続してたらそのうち何本残るかを返す
double P[3];
double dfs(int year, int rest) {
if (year == 0) return (double)rest;
if (rest <= 0) return 0;
if (memo[year][rest] >= 0) return memo[year][rest];
if (rest == 1) {
return (1-P[0]) * dfs(year-1, rest);
} else {
double ret = 0;
for (int s = 0; s < (1<<rest); s++) {
// まずそのような状態になる確率を求める
double p = 1;
for (int i = 0; i < rest; i++) {
if ((s>>i)&1) {
if (i == 0) p *= (1-P[1]);
else if (i == rest-1) p *= (1-P[1]);
else p *= (1-P[2]);
} else {
if (i == 0) p *= P[1];
else if (i == rest-1) p *= P[1];
else p *= P[2];
}
}
// 次に分割分だけdfsして期待値を出す
for (int cur = 0; cur < rest; cur++) {
if ((s>>cur)&1) {
int i = cur;
while ((s>>i)&1) i++;
ret += p*dfs(year-1, i-cur);
cur = i;
}
}
}
return memo[year][rest] = ret;
}
}
int main(void) {
int A;
cin >> A;
for (int i = 0; i < 25; i++) for (int j = 0; j < 20; j++) {
memo[i][j] = -1;
}
for (int i = 0; i < 3; i++) {
cin >> P[i];
P[i] /= 100.0;
}
printf("%.10lf\n", dfs(80-A, 14) * 2);
return 0;
}
mayoko_