码迷,mamicode.com
首页 > 其他好文 > 详细

[CF16E]Fish

时间:2020-07-30 22:14:38      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:span   ==   std   cst   mes   就是   解释   ret   spl   

[CF16E]Fish

一.前言

? 一开始位运算没有打括号导致优先级混乱还真是对不起了。题目链接

二.思路

? 提前声明,为了保证位运算起来方便,鱼的编号从0开始,并且状态的标志为最后一位是编号为0的鱼。

? 这题的转移可以说是十分好想了,对于一个状态(表示还有多少鱼存活),我们从里面抽一个鱼出来让它被吃掉,至于被谁吃暂且不知道。那么转移方程就可以表达出来。

\[f[i-(1<<u)]+=f[i]*P*a_{ku} \]

这里稍加解释,u是被吃掉的鱼,k则是吃它的鱼,P为k碰到u的概率,计原先的鱼群中鱼的个数为cnt,那么很显然\(P=2*\dfrac{1}{cnt*(cnt-1)}=\dfrac{1}{cnt*(cnt-1)/2}\),之后就是很正常的状压DP的操作了,看代码吧。

三.CODE

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=(1<<18)-1;
double f[MAXN+1],a[19][19];
int n,cnt[MAXN+1],maxn;
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;++i)
		for(int j=0;j<n;++j)scanf("%lf",&a[i][j]);
	maxn=(1<<n)-1;f[maxn]=1.0;cnt[maxn]=n;//一开始所有鱼都存在的概率为1
	for(int i=maxn,v;i>=3;--i){
		v=cnt[i]*(cnt[i]-1)/2;//提前处理一下
		if(f[i])//用f[i]来转移
		for(int u=0;u<n&&(1<<u)<=i;++u){//抽一条鱼出来
			if(((1<<u)&i)==0)continue;
			int j=i^(1<<u);
			cnt[j]=cnt[i]-1;//记录剩余的鱼的数量
			for(int x=0;x<n;++x)//枚举哪条鱼吃它
				if((1<<x)&j)f[j]+=f[i]*1.0/v*a[x][u];//转移
		}
	}
	for(int i=0;i<n;++i)printf("%.6lf ",f[1<<i]);
	return 0;
}

[CF16E]Fish

标签:span   ==   std   cst   mes   就是   解释   ret   spl   

原文地址:https://www.cnblogs.com/clockwhite/p/13406074.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!