标签:span == std cst mes 就是 解释 ret spl
? 一开始位运算没有打括号导致优先级混乱还真是对不起了。题目链接
? 提前声明,为了保证位运算起来方便,鱼的编号从0开始,并且状态的标志为最后一位是编号为0的鱼。
? 这题的转移可以说是十分好想了,对于一个状态(表示还有多少鱼存活),我们从里面抽一个鱼出来让它被吃掉,至于被谁吃暂且不知道。那么转移方程就可以表达出来。
这里稍加解释,u是被吃掉的鱼,k则是吃它的鱼,P为k碰到u的概率,计原先的鱼群中鱼的个数为cnt,那么很显然\(P=2*\dfrac{1}{cnt*(cnt-1)}=\dfrac{1}{cnt*(cnt-1)/2}\),之后就是很正常的状压DP的操作了,看代码吧。
#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;
}
标签:span == std cst mes 就是 解释 ret spl
原文地址:https://www.cnblogs.com/clockwhite/p/13406074.html