• 【NOIP2016提高A组模拟7.17】锦标赛


    题目

    403机房最近决定举行一场锦标赛。锦标赛共有N个人参加,共进行N-1轮。第一轮随机挑选两名选手进行决斗,胜者进入下一轮的比赛,第二轮到第N-1轮再每轮随机挑选1名选手与上一轮胜利的选手决斗,最后只剩一轮选手。第i名选手与第j名选手决斗,第i名选手胜利的概率是a[i][j].
    作为一号选手的富榄想知道如何安排每轮出场的选手可以使得他获胜的概率最大,并求出这个最大概率。

    分析

    (f[i][j])表示剩下的人集合为j,当前胜者为i,我们在向后一轮转移时发现有胜败两种情况,从前向后转会转移入两个状态,这用是不可以的。
    所以我们要从后一轮向前一轮转移,把两个状态合入一个状态。

    [f_{i,j}=maxleft{egin{array}\f_{i,j-2^{k}}*a_{i,k}+f_{k,j-2^{i}}*a_{k,i}\f_{i,j}end{array} ight. ]

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const int maxlongint=2147483647;
    const int mo=1000000007;
    const int N=50005;
    using namespace std;
    double f[20][262150],a[20][20],ans;
    int n,mi[20],d[20][262150];
    int main()
    {
    	scanf("%d",&n);
    	mi[0]=1;
    	for(int i=1;i<=n;i++) 
    	{
    		mi[i]=mi[i-1]*2;
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			scanf("%lf",&a[i][j]);
    	for(int i=1;i<=mi[n]-1;i++)
    	{
    		int j=i,sum=0;
    		while(j)
    		{
    			if(j&1) sum++;
    			j/=2;
    		}
    		d[sum][++d[sum][0]]=i;
    	}
    	f[1][1]=1;
    	for(int i=2;i<=n;i++)
    	{
    		for(int k=1;k<=d[i][0];k++)
    			for(int j=1;j<=n;j++)
    				if((d[i][k]&mi[j-1])==mi[j-1])
    					for(int l=1;l<=n;l++)
    						if((d[i][k]&mi[l-1])==mi[l-1])
    							f[j][d[i][k]]=max(f[j][d[i][k]],f[j][d[i][k]-mi[l-1]]*a[j][l]+f[l][d[i][k]-mi[j-1]]*a[l][j]);
    	}
    	for(int i=1;i<=n;i++)
    		ans=max(f[i][mi[n]-1],ans);
    	printf("%.7lf",ans);
    }
    
  • 相关阅读:
    单机安装hadoop+hive+presto
    java ListMap使用多个key比较
    java多线程-3-使用多线程的时机
    java多线程-2-概念和实现机制
    mysql的varchar和oracle的varchar2比较
    js-对象创建
    java关于json的一些问题
    spring使用RedisCacheManager管理key的一些问题
    如何提高工作效率
    关系数据库之-事务
  • 原文地址:https://www.cnblogs.com/chen1352/p/9013526.html
Copyright © 2020-2023  润新知