poj 3071 【概率dp】

来源:互联网 发布:破解激活码软件 编辑:程序博客网 时间:2024/05/21 17:32

题目链接:poj 3071 Football


题意:有2^n只足球队,已知你两两足球队间的胜率p[i][j](足球队i赢足球队j的概率),赛制为单轮淘汰制并且每轮中剩余队伍序号1与2对战,3与4对战,5与6对战...问n轮过后哪只足球队的胜率最大。


题解:设dp[i][j]为第i轮第j只队伍获胜的概率,

转移方程如下:

dp[i][j] += dp[i-1][j]*p[j][k]*dp[i-1][k]

k为第i轮可能与j对战的球队

这里k与i和j是存在关系的,可以写下可能的对战序列进行观察,这里取八只队伍:

第一轮 1:(2) 2:(1) 3:(4) 4:(3) 5:(6) 6:(5) 7:(8) 8:(7)

第二轮 1:(3,4) 2:(3,4) 3:(1,2) 4:(1,2) 5:(7,8) 6:(7,8) 7:(5,6) 8:(5,6)

第三轮 1:(5,6,7,8) 2:(5,6,7,8) 3:(5,6,7,8) 4:(5,6,7,8) 5:(1,2,3,4) 6:(1,2,3,4) 7:(1,2,3,4) 8:(1,2,3,4)

从上面就可以找到规律确定k的范围


#include<iostream>#include<stdio.h>#include<algorithm>#include<cmath>#include<stdlib.h>#include<string.h>#include<queue>#include<set>#include<map>#include<stack>#include<time.h>#include<sstream>using namespace std;#define MAX_N 100005#define inf 0x3f3f3f3f#define LL long  long#define ull unsigned long longconst LL INF = 1e18;const double eps = 1e-8;//const int mod = 1e9+7;//const double pi = acos(-1);typedef pair<int, int>P;double p[1<<8][1<<8];double dp[10][1<<8];int pow2(int k){    int ans = 1;    while(k) {        k--;        ans *= 2;    }    return ans;}int cal(int a, int b){    return (b/a)+1;}int main(){    int n;    while(cin >> n && n!=-1) {        for(int i=0; i<(1<<n); i++)            for(int j=0; j<(1<<n); j++)                scanf("%lf", &p[i][j]);        memset(dp, 0, sizeof(dp));        for(int i=0; i<(1<<n); i++)            dp[0][i] = 1;        for(int i=1; i<=n; i++) {            for(int j=0; j<(1<<n); j++) {                int m = pow2(i-1);                int pos = cal(2*m, j);                int mid = (2*pos-1)*m;                int s, e;                if(j < mid) {                    s = mid;                    e = pos*m*2;                }                else {                    s = (pos-1)*m*2;                    e = mid;                }                //printf("%d %d %d %d\n", i, j, s, e);                for(int k=s; k<e; k++) {                    dp[i][j] += dp[i-1][j]*p[j][k]*dp[i-1][k];                }            }            //puts("");        }        int idx = 0;        for(int i=0; i<(1<<n); i++) {            //printf("%.3lf ", dp[n][i]);            if(dp[n][i] > dp[n][idx])                idx = i;        }        //puts("");        cout << idx+1 << endl;    }}

代码写的略渣了点。。

0 0
原创粉丝点击