版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/88658611
题面:
在一片大海上有n个岛屿,规划建设m座桥,第i座桥的成本为zi,但由于海怪的存在,第i座桥有pi的概率不能建造。
求在让岛屿尽量联通的情况下,期望最小成本为多少。
尽量联通:在对每座桥确定能否建造的情况下,对于任意两个岛屿,如果存在一种建桥方案使得它们联通,那么它们必须联通。
n≤14,m≤n(n−1)2
题目分析:
装呀DP?
似乎还是很显然吧。。
对于
,可以直接计算前
条边中任意点集的所有p的乘积
PPT中的
就可以表示为
Code:
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define maxn 15
#define rg register
using namespace std;
template<class T>inline void read(T &a){
char c;while(!isdigit(c=getchar()));
for(a=c-'0';isdigit(c=getchar());a=a*10+c-'0');
}
struct node{
int u,v,z;double p;
bool operator < (const node &B)const{return z<B.z;}
}e[maxn*maxn];
int n,m;
double ans,f[1<<maxn],h[1<<maxn],tmp;
int main()
{
read(n),read(m);
for(int i=1;i<=m;i++) read(e[i].u),read(e[i].v),read(e[i].z),scanf("%lf",&e[i].p);
sort(e+1,e+1+m);
for(int i=0;i<(1<<n);i++) h[i]=1;
for(int i=0;i<n;i++) f[1<<i]=1;
for(int k=1;k<=m;k++){
rg int x=1<<(e[k].u-1),y=1<<(e[k].v-1),xy=x|y;
rg int s=((1<<n)-1)^xy;
for(rg int i=s;;i=(i-1)&s) if(f[i|x]){//有很多状态都是0
rg int t=s^i;
for(rg int j=t;;j=(j-1)&t) if(f[j|y]){
f[i|j|xy]+=(tmp=(1-e[k].p)*f[i|x]*f[j|y]/h[i|j|xy]*h[i|x]*h[j|y]);
ans+=e[k].z*tmp;
if(!j) break;
}
if(!i) break;//注意这里的集合都可以为空
}
for(rg int t=s;;t=(t-1)&s){
f[t|x]*=e[k].p;
f[t|y]*=e[k].p;
h[t|xy]*=e[k].p;
if(!t) break;
}
}
printf("%.6f",ans);
}