【codeforces 175D】 Plane of Tanks: Duel

http://codeforces.com/problemset/problem/175/D (題目連接)ios

題意

  A,B兩人玩坦克大戰,坦克有生命值,射擊間隔,傷害範圍,未命中的機率。問A贏的機率是多少。數組

Solution

  直接作並很差作,注意到精度要求只有$10^{-4}$,也就是說當射擊次數達到必定上限以後,知足了精度要求咱們就能夠不作了。咱們考慮按照時間dp。怎麼設計狀態呢,若是$f[i][j]$表示A還剩$i$點生命值,B還剩$j$點生命值,這樣複雜度過高了,咱們考慮將A和B剩餘生命分開dp。spa

  $f[i][j]$表示A被射擊$i$次後,還剩下$j$點生命值的機率,特殊的,$f[i][0]$表示在射擊次數$<=i$時A死亡的機率。B的同理。轉移很顯然:$$f[i][max(0,j-x)]=f[i-1][j]*(1-p)/(r-l+1)+f[i-1][j]*p$$設計

  咱們預處理出$D$次射擊後A,B的dp數組。考慮怎麼計算答案。若是B在第$K$輪掛掉了,那麼要求A在第$K$輪射擊以前沒有死,那麼這個時候A被射擊了多少次呢,咱們能夠算出來:$$T=((K-1)*dt_A+dt_B-1)/dt_B$$code

  那麼A在第$K$輪勝出的機率爲:$$ans_K=(1-f_A[T][0])*f_B[K][0]$$blog

  最後把全部的$ans$累加起來就能夠了。get

細節

  mdzz寫了半天,各類坑點,本機1s多CF上竟然TLE了是什麼鬼嘛,智力-2。string

  時間設到4000差很少夠了。it

   當$f[i][j]==0$的時候不dp,可是!可是!!要這樣寫:$f[i][j]<=eps$。。一把辛酸淚啊T_Tio

  要特判$p_A=100$和$p_B=100$的狀況,並且前者必定要寫在後者以前T_T。

代碼

// codeforces175D
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<ctime>
#define LL long long
#define eps 1e-8
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

double f[2][4010][210],p[2],ans;
int hp[2],dt[2],L[2],R[2],P[2],n,x;

int main() {
	for (int i=0;i<2;i++) scanf("%d%d%d%d%d",&hp[i],&dt[i],&L[i],&R[i],&P[i]);
	if (P[0]==100) {puts("0");return 0;}  //must first
	if (P[1]==100) {puts("1");return 0;}
	f[0][0][hp[0]]=f[1][0][hp[1]]=1;p[0]=P[0]/100.0;p[1]=P[1]/100.0;
	for (x=1;x<=4000;x++) {
		for (int i=0;i<2;i++)
			for (int l=i^1,j=1;j<=hp[i];j++) {
				if (f[i][x-1][j]<=eps) continue;
				for (int k=L[l];k<=R[l];k++) 
					f[i][x][max(0,j-k)]+=f[i][x-1][j]*(1-p[l])/(R[l]-L[l]+1);
				f[i][x][j]+=f[i][x-1][j]*p[l];
			}
		f[0][x][0]+=f[0][x-1][0];
	}
	for (int i=1;i<=x;i++) {
		int T=((i-1)*dt[0]+dt[1]-1)/dt[1];
		if (T>x) break;
		ans+=(1-f[0][T][0])*f[1][i][0];
	}
	printf("%.6lf\n",ans);
	return 0;
}
相關文章
相關標籤/搜索