Horsemeet (胜负的概率)

原题: https://cn.vjudge.net/problem/Gym-101954G

题意:

8*8的棋盘,已知两个马(走日,无马脚,每次往各个可行方向走的概率相同)的位置,黑马先走,吃法同中国象棋,问黑马赢的概率大还是白马

解析:

直接暴力每次走完后落在64个格子上的概率
设:当前由 v 0 v 1 v_0\to v_1 v 0 v_0 k k 个方向可以走,当前马的概率为 W W ,对面马的概率 B B

那么显然此时获胜的的概率为: W ( v 1 ) B ( v 1 ) W(v_1)*B(v_1)

接下来是难点,怎么维护 W ? W?
对于任何一个 v 0 v_0 可以走到的点的概率就直接是 1 / k 1/k 吗?实则不然,因为如果上一次对面和落在 v 0 v_0 ,也就是说之前我已经赢了,那么这部分情况是没有后续的,所以,概率应该是 W ( v 0 ) × ( 1 / k ) × ( 1 B ( v 0 ) ) W(v_0)\times (1/k)\times(1-B(v_0))

#include<bits/stdc++.h>
using namespace std;
typedef double F;

F a[8][8],b[8][8];
const double eps = 1e-6;
int di[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}};

F val[8][8];
void init(){
    for(int i=0;i<8;i++){
        for(int j=0;j<8;j++){
            int co=0;
            for(int k=0;k<8;k++){
                int x=i+di[k][0],y=j+di[k][1];
                if(x<0||x>=8||y<0||y>=8)continue;
                co++;
            }
            val[i][j]=1.0/(F)co;
        }
    }
}

int main(){
    init();
    int aa,ab,c,d;cin>>aa>>ab>>c>>d;
    a[aa-1][ab-1]=1,b[c-1][d-1]=1;
    F v1=0,v2=0;
    bool f=0;
    while(1){
        F aa[8][8],bb[8][8];
        memset(aa,0,sizeof(aa));
        memset(bb,0,sizeof(bb));
        for(int i=0;i<8;i++){
            for(int j=0;j<8;j++){
                for(int k=0;k<8;k++){
                    int x=i+di[k][0],y=j+di[k][1];
                    if(x<0||x>=8||y<0||y>=8)continue;
                    aa[x][y]+=a[i][j]*val[i][j]*(1.0-b[i][j]);

                }
            }
        }
        //double S=0;
        for(int i=0;i<8;i++){
            for(int j=0;j<8;j++){
                a[i][j]=aa[i][j];
                //S+=a[i][j];
                v1+=a[i][j]*b[i][j];
            }
        }
        //printf("%.5f\n",S);
        if(v1-0.5>eps){
            f=1;printf("white\n");break;
        }
        for(int i=0;i<8;i++){
            for(int j=0;j<8;j++){
                for(int k=0;k<8;k++){
                    int x=i+di[k][0],y=j+di[k][1];
                    if(x<0||x>=8||y<0||y>=8)continue;
                    bb[x][y]+=b[i][j]*val[i][j]*(1.0-a[i][j]);
                }
            }
        }
        for(int i=0;i<8;i++){
            for(int j=0;j<8;j++){
                b[i][j]=bb[i][j];
                v2+=a[i][j]*b[i][j];
            }
        }
        if(v2-0.5>eps){
            f=1;printf("black\n");break;
        }
    }
    if(!f)printf("draw\n");
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/84191743