2018 acmicp徐州网络赛 Cacti Lottery 暴力模拟

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lifelikes/article/details/82596672

点我看题

题意:给出一种游戏的规则,balabalabala,要你求出最后结果的期望。

解题思路:
由于是一个九宫格 所有情况也只有9*9 直接枚举也不会超时。
题目中有*和#号两种位置方格,对于我们来说都是未知的,但对于游戏选手来说只有#是未知的,所以要分开来考虑。
也就是说,题目要求的期望,其实是期望的期望。。。
知道这点后,就可以暴力去枚举了。
复杂度O(能过)

#include <bits/stdc++.h>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;
const int MOD = 1e9+7;
char str[5][5];
int maps[5][5];
vector<int> res;
int vis[10];
int val[40];
double ans;
int cntans[8];
void init() {
    val[6]=10000;
    val[7]=36;
    val[8]=720;
    val[9]=360;
    val[10]=80;
    val[11]=252;
    val[12]=108;
    val[13]=72;
    val[14]=54;
    val[15]=180;
    val[16]=72;
    val[17]=180;
    val[18]=119;
    val[19]=36;
    val[20]=360;
    val[21]=1080;
    val[22]=144;
    val[23]=1800;
    val[24]=3600;
    ans=0;
}
int dir[8][3]= {{0,1,2},{3,4,5},{6,7,8},{0,3,6},{1,4,7},{2,5,8},{0,4,8},{2,4,6}};
map<int,bool> M;
int getmax() {
    int ans=0;
    for(int i=0; i<8; i++) {
        int cnt =0;
        for(int j=0; j<3; j++) {
            int x = dir[i][j]/3,y=dir[i][j]%3;
            cnt+=maps[x][y];
        }
        ans=max(ans,(int)val[cnt]);
    }
    return ans;
}
void check(int numa,int numb) {
    int cnt=0;
    for(int i=0; i<numa; i++) {
        cnt = cnt*10+res[i];
    }
    if(M[cnt]==true) {
        return;
    } else {
        M[cnt]=1;
    }
    int now = 0;
    int num = 0;
    for(int i=0; i<3; i++) {
        for(int j=0; j<3; j++) {
            if(str[i][j]=='*') {
                maps[i][j]=res[now];
                now++;
            } else if(str[i][j]!='#') {
                maps[i][j]=str[i][j]-'0';
            }
        }
    }
    vector<int> V;
    for(int i=0; i<numb; i++) {
        V.push_back(res[i+numa]);
    }
    sort(V.begin(),V.end());
    for(int i=0; i<8; i++) {
        cntans[i]=0;
    }
    do {
        now = 0;
        for(int i=0; i<3; i++) {
            for(int j=0; j<3; j++) {
                if(str[i][j]=='#') {
                    maps[i][j]=V[now];
                    now++;
                }
            }
        }
        //double maxs = getmax();

        for(int i=0; i<8; i++) {
            int cnt =0;
            for(int j=0; j<3; j++) {
                int x = dir[i][j]/3,y=dir[i][j]%3;
                cnt+=maps[x][y];
            }
            cntans[i]+=val[cnt];
        }
    } while(next_permutation(V.begin(),V.end()));
    double maxs=0;
    for(int i=0; i<8; i++) {
        maxs = max(maxs,1.0*cntans[i]);
    }
    for(int i=1; i<=numb; i++) {
        maxs/=i;
    }
    ans+=maxs;
    //cout<<ans<<endl;
}
long long comb(int m,int n) {
    if(n==0) return 1;
    if(n==1) return m;
    if(n>m/2) return comb(m,m-n);
    if(n>1) return (comb(m-1,n-1)+comb(m-1,n));
}
int main() {
    int T;
    cin>>T;
    while(T--) {
        for(int i=0; i<3; i++) {
            scanf("%s",str[i]);
        }
        init();
        int numa=0,numb=0;
        memset(vis,0,sizeof vis);
        M.clear();
        res.clear();
        for(int i=0; i<3; i++) {
            for(int j=0; j<3; j++) {
                if(str[i][j]!='#' && str[i][j]!='*') {
                    vis[str[i][j]-'0']=1;
                }
                numa+=str[i][j]=='*';
                numb+=str[i][j]=='#';
            }
        }
        for(int i=1; i<=9; i++) {
            if(!vis[i]) {
                res.push_back(i);
            }
        }
        sort(res.begin(),res.end());
        do {
            check(numa,numb);
        } while(next_permutation(res.begin(),res.end()));
        for(int i=1; i<=numa; i++) {
            ans/=i;
        }
        printf("%.6f\n",ans/comb(numa+numb,numa));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lifelikes/article/details/82596672