zoukankan      html  css  js  c++  java
  • Codeforces 859D

    题意

    (2^n) 个人要进行比赛,每次 (2i)(2i+1) 号人进行比赛((iin [0,2^{n-1})) )。这一轮中赢的人进入下一轮。下一轮比赛的时候把进入这一轮的人按编号排好,仍然是像之前那样相邻的进行一次比赛。最后只剩下一个人。

    数据给出对于 (x,y)(x) 打赢 (y) 的概率。

    (i) 轮比赛会角逐出 (2^{n-i}) 个赢家。我们要在比赛开始前,猜每轮的赢家(一轮的赢家一定要是上一轮的赢家)。第 (i) 轮每猜中一个赢家就会得到 (2^{i-1}) 的得分。

    求最大的期望得分。

    (nle 6)

    分析

    只有猜到了与最终赢家相关的人才可能有得分。

    轮数编号为 ([0,n))

    (f[i][x])(x) 在第 (i) 轮胜利,只统计与 (x) 有关的人(递归地定义,与 (x) 比赛过的人以及与他们有关的人)的猜测的得分。

    这是容易转移的。设 (o(i,x)) 表示可能在第 (i) 轮与 (x) 比赛的人的集合,那么

    [f[i][x]=f[i-1][x]+p[i][x]*2^i+max _{vin o(i,x)}f[i-1][v] ]

    其中 (p[i][x]) 表示 (x) 在第 (i) 轮胜利的概率。 其实就是 (x) 一定要赢,看预测哪个对手得分比较高。

    (p[i][x]) 也是容易得到的

    [p[i][x]=p[i-1][x]*sum _{vin o(i,x)}p[i-1][v]*w[x][v] ]

    (w[x][v])(x) 打败 (v) 的概率。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    inline char nchar() {
    	static const int bufl=1<<20;
    	static char buf[bufl],*a=NULL,*b=NULL;
    	return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
    }
    inline int read() {
    	int x=0,f=1;
    	char c=nchar();
    	for (;!isdigit(c);c=nchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=nchar()) x=x*10+c-'0';
    	return x*f;
    }
    template<typename T> inline void Max(T &x,T y) {if (y>x) x=y;}
    const int maxn=6;
    const int maxs=1<<maxn;
    double a[maxs][maxs],p[maxn][maxs],f[maxn][maxs];
    int n,s,bin[maxs];
    vector<int> o[maxs][maxn];
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	for (int i=2;i<maxs;++i) bin[i]=bin[i>>1]+1;
    	n=read(),s=1<<n;
    	for (int i=0;i<s;++i) for (int j=0;j<s;++j) {
    		a[i][j]=read()/100.;
    		if (i!=j) o[i][bin[i^j]].push_back(j);
    	}
    	for (int i=0;i<s;++i) f[0][i]=p[0][i]=a[i][o[i][0][0]];
    	for (int i=1;i<n;++i) for (int j=0;j<s;++j) {
    		double &r=p[i][j]=0;
    		for (int x:o[j][i]) r+=p[i-1][x]*a[j][x];
    		r*=p[i-1][j];
    	}
    	for (int i=1;i<n;++i) for (int j=0;j<s;++j) {
    		double &r=f[i][j]=0;
    		for (int x:o[j][i]) Max(r,f[i-1][x]);
    		r+=f[i-1][j]+p[i][j]*(1<<i);
    	}
    	double ans=*max_element(f[n-1],f[n-1]+s);
    	printf("%.12lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    python闭包和装饰器
    Redis订阅与发布
    Redis压缩列表
    Linux操作系统--定时任务
    python模块--zipfile文件压缩
    Xshell工具使用--连接VMware虚拟机
    Django数据库--事务及事务回滚
    HTTP长连接--Keep-Alive
    MySQL触发器
    Kasaraju算法--强连通图遍历及其python实现
  • 原文地址:https://www.cnblogs.com/owenyu/p/7763165.html
Copyright © 2011-2022 走看看