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;
    }
    
  • 相关阅读:
    常见总结
    手机号中间四位替换为****
    写给30岁之前的我
    顺序栈ADT简单的实现
    快速排序
    关于存储类的例子总结
    非有序的静态查找表的查找某个元素的算法
    有序的静态查找表的折半(二分)查找算法
    【项目】项目125
    【项目】项目132
  • 原文地址:https://www.cnblogs.com/clockwhite/p/13406074.html
Copyright © 2011-2022 走看看