【NOIP2016提高A组模拟7.17】锦标赛
2016-07-17 16:09
246 查看
题目
403机房最近决定举行一场锦标赛。锦标赛共有N个人参加,共进行N-1轮。第一轮随机挑选两名选手进行决斗,胜者进入下一轮的比赛,第二轮到第N-1轮再每轮随机挑选1名选手与上一轮胜利的选手决斗,最后只剩一轮选手。第i名选手与第j名选手决斗,第i名选手胜利的概率是a[i][j].作为一号选手的富榄想知道如何安排每轮出场的选手可以使得他获胜的概率最大,并求出这个最大概率。
分析
设f[i][j]表示剩下的人集合为j,当前胜者为i,我们在向后一轮转移时发现有胜败两种情况,从前向后转会转移入两个状态,这用是不可以的。所以我们要从后一轮向前一轮转移,把两个状态合入一个状态。
fi,j=max{fi,j−2k∗ai,k+fk,j−2i∗ak,ifi,j
#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 -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 -1],ans); printf("%.7lf",ans); }
相关文章推荐
- 天热无聊,用C语言函数指针实现的小函数^_^
- Eclipse之安装及汉化步骤
- Android开发——获取应用数据/缓存大小并清理缓存
- 内存按字节编址,地址区间为[90000H,CFFFFH],若用32K*8bit的存储器芯片构成该内存,需要__块
- C++ read函数读入int整形数据
- Android开发——获取应用数据/缓存大小并清理缓存
- SortedMap接口源码解析
- maven打包可执行jar的方法
- 【Java源码分析】HashMap源码分析
- poj-1006 中国剩余定理
- 【Thinking in Java真题精选】2. 存在继承关系时的类加载顺序
- 点击空白区域隐藏软键盘输入法
- 放电式消除BIOS密码(有图)
- Spark Checkpoint写操作代码分析
- ueditor富文本的使用以及“未找到上传文件”时的解决办法
- CodeForces 248E Piglet's Birthday (概率)
- 数字在排序数组中出现的次数 java
- Service简单学习
- Java基础学习第一天
- 正则表达式语法以及常用