[报告]codeforces 175d Plane of Tanks: Duel
Abstract
codeforces 175d Plane of Tanks: Duel
dp 概率 乱搞
Source
http://codeforces.com/problemset/problem/175/D
Description
战车少女互殴
两辆战车对战,战车有如下属性:hp,射击时间间隔,击中目标概率,伤害值范围(判定击中目标后等概率选一个范围内的值作为给目标的伤害)。hp降为0战车就不能打了。所以这是一个dnd世界
求第二辆车被摧毁的概率。
Solution
我见过的最没节操的概率题……
一开始设计的状态为f(hp0, hp1, t)表示已知当前第一辆车hp为hp0,第二辆车为hp1,时刻为t的时候第二辆车被摧毁的概率。有效的t实际上最大只有lcm(t[0], t[1]),里面还有很多是没用的可以离散化掉。但这样做的markov链是有环的,需要高斯消元。但是状态数实在太多高斯消元肯定超时……
然后就yy了很久,实在想不出来了,去看题解……
题解表示:对于两边根本打不中(击中目标概率为0)的情况特判。否则记f[i][j]表示当前战车i还剩j的hp的概率,模拟整个过程,直到某一边还存活的概率<EPS……
Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const double EPS = 1e-7; int hp[2], dt[2], l[2], r[2], pi[2]; double p[2], a[2]; double f[2][222]; int t[2]; void update(int i) { int j, k; f[i][0] = 0; for (j = 1; j <= hp[i]; ++j) { double h = f[i][j]*(1-p[!i])/(r[!i]-l[!i]+1); f[i][j] *= p[!i]; for (k = l[!i]; k <= r[!i]; ++k) f[i][max(0, j-k)] += h; } for (a[i]=0, j=1; j <= hp[i]; ++j) a[i] += f[i][j]; } int main() { int i, j, k, d; for (i = 0; i < 2; ++i) { cin>>hp[i]>>dt[i]>>l[i]>>r[i]>>pi[i]; p[i] = pi[i]/100.0; } if (pi[0]==100) return puts("0"), 0; else if (pi[1]==100) return puts("1"), 0; a[0] = a[1] = f[0][hp[0]] = f[1][hp[1]] = 1; double ans = 0; for (; a[0]>EPS && a[1]>EPS; ) { i = t[0]<=t[1]?0:1; t[i] += dt[i]; update(!i); if (i==0) ans += a[0]*f[1][0]; } printf("%.6f\n", ans); return 0; }