1. 程式人生 > >P1850 換教室 題解

P1850 換教室 題解

題目連結:-----

題意:

有 v 間教室, 教室之間有 e 條雙向邊連線, 從一個教室走到另一個教室需要一
定時間. 有 n 節課, 第 i 節課有兩間教室, 預設要去第 c[i] 間教室, 可以申請到
第 d[i] 間教室去, 申請通過的概率為 p[i], 所有申請必須在最開始提交. 求出提
交申請個數不超過 m 的情況下, 依次上完這 n 節課期望最少要走多遠.
v ≤ 300, e ≤ 90000, n ≤ 2000.

前置知識:

1.全概率公式:

P(A)=\sum_{i=1}^{n} {P(A|Bi)*P(Bi)}

2.隨機變數是在概率空間的基本變數上定義的函式.
記 E(X) 為隨機變數 X 的期望值

E(X)=\sum_{w=1}^{n} {P(w)*X(w)}

可以看做概率乘以權值。

3.期望具有線性性:

E(aX + Y ) = aE(X) + E(Y )

 

題解思路:

每節課之間要走的路程的期望之和可以根據期望的線性性,

求出每一個路程的期望,累加即可。

1.先用floyd求出最短路。

2.f[i][j][0/1]表示上完第I節課後,用了j次申請,第i節課是否換教室,期望路程的最小值。

3.因為它只是期望,如果有期望得到申請,也得加上期望沒有得到申請的情況。

4.轉移方程比較噁心,我就不貼了。

程式碼:

#include<iostream>
#include
<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> #define ll long long #define R register using namespace std; const int N=2005; const int M=2005; const int INF=200000000; //14299.96 //f[i][j][0/1] 到第i節課 用了 j 個 申請 第i節課換不換的期望 int n,m,v,e,c[N],d[N],far[M][M];
double f[N][N][2],k[N],ans=INF; int main(){ scanf("%d%d%d%d",&n,&m,&v,&e);//時間 次數 點數 邊數 for(R int i=1;i<=n;i++) scanf("%d",&c[i]);//不換 for(R int i=1;i<=n;i++) scanf("%d",&d[i]);// for(R int i=1;i<=n;i++) scanf("%lf",&k[i]);//概率 for(R int i=1;i<=v;i++) for(R int j=1;j<=v;j++) far[i][j]=INF; for(R int i=1;i<=e;i++) { R int u,v; R int w; scanf("%d%d%d",&u,&v,&w); far[u][v]=min(w,far[u][v]); far[v][u]=min(w,far[v][u]); } for(R int i=1;i<=v;i++) far[i][i]=0; for(R int t=1;t<=v;t++) for(R int i=1;i<=v;i++) for(R int j=1;j<=v;j++) far[i][j]=min(far[i][j],far[i][t]+far[t][j]); for(R int i=1;i<=n;i++) for(R int j=0;j<=m;j++) for(R int t=0;t<=1;t++) f[i][j][t]=INF; f[1][0][0]=0; f[1][1][1]=0; for(R int i=2;i<=n;i++) { for(R int j=0;j<=min(m,i);j++) { if(j<=i-1) f[i][j][0]=min( f[i-1][j][0]+ far[c[i-1]][c[i]], f[i-1][j][1]+ far[d[i-1]][c[i]]*k[i-1]+ far[c[i-1]][c[i]]*(1-k[i-1])); if(j!=0) f[i][j][1]=min( f[i-1][j-1][0]+ far[c[i-1]][d[i]]*k[i]+ far[c[i-1]][c[i]]*(1-k[i]), f[i-1][j-1][1]+ far[d[i-1]][d[i]]*k[i]*k[i-1]+ far[c[i-1]][d[i]]*(1-k[i-1])*k[i]+ far[d[i-1]][c[i]]*(1-k[i])*k[i-1]+ far[c[i-1]][c[i]]*(1-k[i])*(1-k[i-1])); } } for(R int i=0;i<=m;i++){ if(i<=n-1) ans=min(ans,f[n][i][0]); if(i!=0) ans=min(ans,f[n][i][1]); } printf("%.2lf",ans); return 0; }