您的位置:首页 > 其它

关于CSU 1725以及CodeForce 148D自己的解法

2016-08-03 11:10 253 查看
                 老实说那几天自己还不会概率DP,就按照自己的野路子来了。。但是发现也还是能够做出来,时间也和别人的差不多。。

                 感觉忘记太可惜了,于是特此记录下来。

                 数据结构:队列

                 例题:CSU 1725

                 我一开始的想法是用一个五维数组来表示,double arr[a][b][c][d][e] ,a表示余剩攻击次数,b表示余剩血量,c,d,e分别表示余剩的1,2,3血的奴隶主,而                   arr[a][b][c][d][e]储存的是发生这个局面的概率。

                 由一个局面到达另外一个局面的情况只有5种,攻击英雄致死,攻击英雄未致死,攻击一血奴隶主,攻击二血奴隶主并产生一个新的,攻击二血奴隶主

            未产生新的,攻击三血的情况同攻击二血的。

                因此,我采用一个结构体Node,Node有5个数据成员,含义同五维数组的下标,当首先把最初的局面加入队列,然后通过不断的取队列的front来不断推演,停止演算的条件是英雄血量为0或者是余剩次数为0

            接下来发生的局面,并且同时更新arr五维数组,也就是说,最终在五维数组里面储存的是各个局面发生的概率,我只需要把这个五维数组遍历一遍,取出我想要的局面的  概率,都加起来即可。

           PS:flag数组的含义和SPFA里面的一个bool数组差不多,用于表示某一个局面是否已经在队列中存在。

           代码:(在所有AC的人里面,我的代码是最长的。。。。。)

         

#include<iostream>
#include<queue>
#include<cstring>

using namespace std;

int t,x,y,z,num;
struct Node{
int times,health,num1,num2,num3;
Node(int e=0,int a=0,int b=0,int c=0,int d=0):times(e),health(a),num1(b),num2(c),num3(d){};
}te;

queue<Node> q;

double arr[25][25][8][8][8],probaboly;
bool flag[25][25][8][8][8];

int main(){
ios_base::sync_with_stdio(false);
cout.setf(ios_base::fixed);
cout.precision(6);
cin>>t;
while(t--){
cin>>x>>y>>z;
if(x<y)
cout<<"0.000000\n";
else{
arr[x][y][0][0][z]=1;q.push({x,y,0,0,z});
flag[x][y][0][0][z]=true;
while(!q.empty()){
te=q.front();q.pop();flag[te.times][te.health][te.num1][te.num2][te.num3]=false;
//cout<<te.times<<' '<<te.health<<' '<<te.num1<<' '<<te.num2<<' '<<te.num3<<endl;
if(te.health==0)
continue;
if(te.times!=0){
num=1+te.num1+te.num2+te.num3;

if(te.health!=0){
arr[te.times-1][te.health-1][te.num1][te.num2][te.num3]+=arr[te.times][te.health][te.num1][te.num2][te.num3]/num;
if(!flag[te.times-1][te.health-1][te.num1][te.num2][te.num3])
q.push({te.times-1,te.health-1,te.num1,te.num2,te.num3}),flag[te.times-1][te.health-1][te.num1][te.num2][te.num3]=true;
}

if(te.num1!=0){
arr[te.times-1][te.health][te.num1-1][te.num2][te.num3]+=arr[te.times][te.health][te.num1][te.num2][te.num3]*te.num1/num;
if(!flag[te.times-1][te.health][te.num1-1][te.num2][te.num3])
q.push({te.times-1,te.health,te.num1-1,te.num2,te.num3}),flag[te.times-1][te.health][te.num1-1][te.num2][te.num3]=true;
}

if(te.num2!=0){
if(num<8){
arr[te.times-1][te.health][te.num1+1][te.num2-1][te.num3+1]+=arr[te.times][te.health][te.num1][te.num2][te.num3]*te.num2/num;
if(!flag[te.times-1][te.health][te.num1+1][te.num2-1][te.num3+1])
q.push({te.times-1,te.health,te.num1+1,te.num2-1,te.num3+1}),flag[te.times-1][te.health][te.num1+1][te.num2-1][te.num3+1]=true;
}
else{
arr[te.times-1][te.health][te.num1+1][te.num2-1][te.num3]+=arr[te.times][te.health][te.num1][te.num2][te.num3]*te.num2/num;
if(!flag[te.times-1][te.health][te.num1+1][te.num2-1][te.num3])
q.push({te.times-1,te.health,te.num1+1,te.num2-1,te.num3}),flag[te.times-1][te.health][te.num1+1][te.num2-1][te.num3]=true;
}
}
if(te.num3!=0){
if(num<8){
arr[te.times-1][te.health][te.num1][te.num2+1][te.num3]+=arr[te.times][te.health][te.num1][te.num2][te.num3]*te.num3/num;
if(!flag[te.times-1][te.health][te.num1][te.num2+1][te.num3])
q.push({te.times-1,te.health,te.num1,te.num2+1,te.num3}),flag[te.times-1][te.health][te.num1][te.num2+1][te.num3]=true;
}
else{
arr[te.times-1][te.health][te.num1][te.num2+1][te.num3-1]+=arr[te.times][te.health][te.num1][te.num2][te.num3]*te.num3/num;
if(!flag[te.times-1][te.health][te.num1][te.num2+1][te.num3-1])
q.push({te.times-1,te.health,te.num1,te.num2+1,te.num3-1}),flag[te.times-1][te.health][te.num1][te.num2+1][te.num3-1]=true;
}
}
}
}
for(int m=x-y;m>=0;--m)
for(int i=0;i<=7;++i)
for(int j=0;j<=7-i;++j)
for(int k=0;k<=7-i-j;++k)
probaboly+=arr[m][0][i][j][k];//,cout<<m<<' '<<i<<' '<<j<<' '<<k<<' '<<arr[m][0][i][j][k]<<endl;

//cout<<arr[0][0][0][0][1]<<' '<<arr[0][0][0][1][1]<<endl;
cout<<probaboly<<endl;memset(arr,0,sizeof(arr));probaboly=0;//memset(flag,0,sizeof(flag));
}
}
return 0;
}


         CodeForce 148D:原来是是一个龙和公主抓老鼠的故事,这种事情当然是要公主赢才是。。而且公主的意见也很不错呀。。龙为什么就不听话呢。。。
         扯远了。。咳咳,下面是正题
         同样的,使用一个结构体来表示到达这个局面的概率,然后数组更新完毕之后,回过头去,在每一种状态的下算一遍公主胜利的概率。
         至于局面终止的情况,就是没有白色的老鼠了
        
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;

int w,b;
double arr[1010][1010],sum;
struct Node{
int w,b;
Node(int a =0,int c=0):w(a),b(c){};
}te;
bool flag[1010][1010];

queue<Node> q;

int main(){
while(scanf("%d",&w)!=EOF){
scanf("%d",&b);
arr[w][b]=1;q.push({w,b});
while(!q.empty()){
te=q.front();q.pop();flag[te.w][te.b]=false;
if(te.w&&!te.b)continue;
if(te.w>0&&te.b>1){
arr[te.w-1][te.b-2]+=arr[te.w][te.b]*te.b/(te.b+te.w)*(te.b-1)/(te.b+te.w-1)*te.w/(te.b+te.w-2);
if(!flag[te.w-1][te.b-2])
q.push({te.w-1,te.b-2}),flag[te.w-1][te.b-2]=true;
}
if(te.b>2){
//printf("%lf %lf ",arr[te.w][te.b-3],arr[te.w][te.b]*te.b/(te.w+te.b)*(te.b-1)/(te.b+te.w-1)*(te.b-2)/(te.b+te.w-2));
arr[te.w][te.b-3]+=arr[te.w][te.b]*te.b/(te.w+te.b)*(te.b-1)/(te.b+te.w-1)*(te.b-2)/(te.b+te.w-2);
//printf("%lf",arr[1][0]);
if(!flag[te.w][te.b-3])
q.push({te.w,te.b-3}),flag[te.w][te.b-3]=true;
}

}

for(int i=1;i<=w;++i){
for(int j=0;j<=b;++j)
sum+=arr[i][j]*i/(i+j);//,printf("%lf %d %d ",arr[i][j],i,j);
}
printf("%.9lf\n",sum);sum=0;memset(arr,0,sizeof(arr));
}
}


         以上,自己的野套路讲解完毕
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐