抄iSea标程的 V5
 /**//*
题意:5个敌人,各自有hp(1<=hp<=5) 现随机扔一个球给一个人,然后这个人的hp就会-1
随后,这个球会随机扔给距离不超过D的另外一个人(不能是自己),收到球的敌人hp-1
当hp=0时死掉
问每个敌人死掉的概率

6维
dp[hp[0]][hp[1]][hp[2]][hp[3]][hp[4]][cur]表示当前球在cur处,每个人的对应的血为hp[i]时的概率
记忆化搜索
一开始时每个人的概率就是0.2了
答案就是只要血为0时的概率累加
用bfs状态比较大
记忆化搜索比较好
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

struct Point
  {
double x,y;
};

double dp[6][6][6][6][6][6];
double ans[6];
int N,D,hp[6],_hp[6],totHp;
Point pt[6];
bool can[6][6];

bool chk(Point &a,Point &b)
  {
return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) <= D*D;
}

double cal(int *_hp,int cur)
  {
double &ans = dp[_hp[0]][_hp[1]][_hp[2]][_hp[3]][_hp[4]][cur];


if(ans >= 0.0) return ans;

ans = 0.0;

int _totHp = 0;
for(int i = 0; i<5;i++)
_totHp += _hp[i];

if(_totHp + N + 1 < totHp) return 0.0;
if(_hp[cur] + 1 > hp[cur])return 0.0;
for(int i=0;i<5;i++)
 {
if(can[i][cur])
 {
int cnt = 0;
int _hp2[6];
for(int j = 0;j<5;j++)
 {
_hp2[j] = _hp[j];
if(j==cur)++_hp2[j];
if(_hp2[j] && can[i][j])cnt++;//can[i][j]
}
ans += cal(_hp2,i)/cnt;
}
}
return ans;
}

int main()
  {
#ifdef ONLINE_JUDGE
#else
freopen("in","r",stdin);
#endif
while( ~scanf("%d%d" ,&N,&D) )
 {
memset(can,0,sizeof(can));
for(int i = 0; i<5; i++)
 {
scanf("%lf%lf",&pt[i].x,&pt[i].y);
for(int j = 0;j<i;j++)
 {
can[i][j] = can[j][i] = chk(pt[i],pt[j]);
}
}

totHp = 0;
for(int i=0;i<5;i++)
 {
scanf("%d",&hp[i]);
totHp += hp[i];
}

for(_hp[0]=0;_hp[0]<=hp[0];_hp[0]++)
for(_hp[1]=0;_hp[1]<=hp[1];_hp[1]++)
for(_hp[2]=0;_hp[2]<=hp[2];_hp[2]++)
for(_hp[3]=0;_hp[3]<=hp[3];_hp[3]++)
for(_hp[4]=0;_hp[4]<=hp[4];_hp[4]++)
for(int i = 0; i<5;i++)
dp[_hp[0]][_hp[1]][_hp[2]][_hp[3]][_hp[4]][i] = -1.0;

dp[hp[0]-1][hp[1]][hp[2]][hp[3]][hp[4]][0] = 0.2;
dp[hp[0]][hp[1]-1][hp[2]][hp[3]][hp[4]][1] = 0.2;
dp[hp[0]][hp[1]][hp[2]-1][hp[3]][hp[4]][2] = 0.2;
dp[hp[0]][hp[1]][hp[2]][hp[3]-1][hp[4]][3] = 0.2;
dp[hp[0]][hp[1]][hp[2]][hp[3]][hp[4]-1][4] = 0.2;
memset(ans,0,sizeof(ans));
for(_hp[0]=0;_hp[0]<=hp[0];_hp[0]++)
for(_hp[1]=0;_hp[1]<=hp[1];_hp[1]++)
for(_hp[2]=0;_hp[2]<=hp[2];_hp[2]++)
for(_hp[3]=0;_hp[3]<=hp[3];_hp[3]++)
for(_hp[4]=0;_hp[4]<=hp[4];_hp[4]++)
for(int i = 0;i<5;i++)
 {
double t = cal(_hp,i);
if(_hp[i]==0)ans[i] += t;//_hp[i]=0时概率就累加
}

for(int i = 0;i<5;i++)
 {
if(i)putchar(' ');
printf("%.3f",ans[i]);
}
puts("");
}
return 0;
}
|
|
常用链接
随笔分类
Links
搜索
最新评论

|
|