zoukankan      html  css  js  c++  java
  • [CF16E]Fish

    [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;
    }
    
  • 相关阅读:
    WinAPI: SetRect 及初始化矩形的几种办法
    [书目20080225]软件工程与项目管理解析
    [转]npkcrypt 服务启动失败
    CPU是为用户服务的
    Web.config基础
    VBScript学习
    [书目20080130]如何成功管理一个软件项目
    [转]DB2常用命令大全
    [转]C++语法概括及其示例(示例代码下载)
    用友华表Cell产生柱状图表
  • 原文地址:https://www.cnblogs.com/clockwhite/p/13406074.html
Copyright © 2011-2022 走看看