題意:兩地之間有n條不相交路徑,第i條路徑由a[i]座橋組成,每座橋有一個損壞機率,讓你肯定一個對全部橋的檢測順序,使得檢測所需的總指望次數最小。spa
首先,顯然檢測的時候,是一條路徑一條路徑地檢測,跳躍地檢測沒有意義。考慮已經排好的某個路徑的順序,相鄰的兩條路徑j和j+1若是知足:blog
(route[j].A+route[j].B)+(route[j+1].A+route[j+1].B)*(1.0-route[j].c)>
(route[j].A+route[j].B)*(1.0-route[j+1].c)+(route[j+1].A+route[j+1].B)排序
就交換它們的順序使得答案變得更優。it
用相似冒泡的方法掃n次便可。io
A是routej的所有橋良好的指望檢查次數,即全部橋好的機率之積乘以橋的數量。B是routej壞的狀況下的指望檢測次數,至關於對每座橋損壞機率從大到小排序,而後對每一個橋k,其前面k-1個橋全好,它壞的機率,乘上k,而後對這個值求和。c是全部橋好的機率之積,即這個路徑好的機率。class
最後輸出答案的時候,對全部路徑求個其前面的全部路徑都壞的機率*(A+B)之和便可。route
#include<cstdio> #include<algorithm> using namespace std; struct data{ double A,B,c; }bridge[1005]; int n,x[1005]; int y[1005]; bool cmp(const int &a,const int &b){ return a>b; } int main(){ //freopen("c.in","r",stdin); scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d",&x[i]); double nowhao=1.0; double huaiall=0; for(int j=1;j<=x[i];++j){ scanf("%d",&y[j]); } sort(y+1,y+x[i]+1); for(int j=1;j<=x[i];++j){ huaiall+=(double)j*nowhao*(1.0-(double)y[j]/1000.0); nowhao*=((double)y[j]/1000.0); } bridge[i].A=nowhao*(double)x[i]; bridge[i].B=huaiall; bridge[i].c=nowhao; } for(int i=1;i<=n;++i){ for(int j=1;j<n;++j){ if((bridge[j].A+bridge[j].B)+(bridge[j+1].A+bridge[j+1].B)*(1.0-bridge[j].c)> (bridge[j].A+bridge[j].B)*(1.0-bridge[j+1].c)+(bridge[j+1].A+bridge[j+1].B)){ swap(bridge[j],bridge[j+1]); } } } double ans=0; double now=1.0; double sum=0; for(int i=1;i<=n;++i){ ans+=now*(bridge[i].A+bridge[i].B); now*=(1.0-bridge[i].c); } printf("%.10f\n",ans); return 0; }