NOIP2016換教室

NOIp級的機率指望(然而我如今仍是須要推第二遍)。c++

能夠獲得很簡單的$dp$定義,$dp[i][j][0/1]$,考慮完前$i$個時間段,進行了$j$次申請,當前此次是否申請的最優指望。數組

剩下的轉移能夠直接分類討論:ide

dp[i][j][0]=min(dp[i-1][j][0]+dis[c[i-1]][c[i]],dp[i-1][j][1]+p[i-1]*dis[d[i-1]][c[i]]+(1-p[i-1])*dis[c[i-1]][c[i]]),因爲這一次咱們沒有申請,因此當上一次也沒有申請的時候只有一種狀況,從上個c到這個c,當上一次申請後,討論申請是否成功,轉移的距離隨着是否成功而變。spa

dp[i][j][1]=min(dp[i-1][j-1][0]+p[i]*dis[c[i-1]][d[i]]+(1-p[i])*dis[c[i-1]][c[i]],dp[i-1][j-1][1]+p[i-1]*p[i]*dis[d[i-1]][d[i]]+p[i-1]*(1-p[i])*dis[d[i-1]][c[i]]+(1-p[i-1])*p[i]*dis[c[i-1]][d[i]]+(1-p[i-1])*(1-p[i])*dis[c[i-1]][c[i]],式子很長,可是思想是同樣的,討論是否成功,來決定dis的下標選擇。code

dis數組能夠直接$Floyd$解出來。blog

有些小細節,點數300,邊數90000,明示重邊,注意$Floyd$不要打醜。get

最優決策$dp$注意初始化問題。it

代碼是最後一週寫的,徹底放飛自個人壓行,看看$dp$式子就完事了。(注意保護眼睛)event

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 inline int read(int sum=0,int f=1,char x=getchar()){
 6     while(x<'0' || x>'9'){
 7         if(x=='-') f=-1; x=getchar();
 8     }while(x>='0' && x<='9'){
 9         sum=sum*10+x-'0';x=getchar();
10     }return sum*f;
11 }
12 
13 int n,m,V,E,c[2050],d[2050],dis[305][305];
14 double p[2050],dp[2050][2050][2],ans=1e14;
15 
16 int main(){
17     n=read(); m=read(); V=read(); E=read();
18     for(int i=1; i<=n; ++i) c[i]=read(); for(int i=1; i<=n; ++i) d[i]=read(); for(int i=1; i<=n; ++i) scanf("%lf",p+i);
19     memset(dis,0x3f,sizeof(dis)); for(int i=1; i<=V; ++i) dis[i][i]=0;
20     for(int i=1,x,y,w; i<=E; ++i) x=read(), y=read(), w=read(), dis[x][y]=min(dis[x][y],w), dis[y][x]=min(dis[y][x],w);
21     for(int k=1; k<=V; ++k) for(int i=1; i<=V; ++i) for(int j=1; j<=V; ++j) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
22     memset(dp,88,sizeof(dp)); dp[0][0][0]=dp[0][0][1]=0; for(int i=0; i<=V; ++i) dis[i][0]=dis[0][i]=0;
23     for(int i=1; i<=n; ++i) for(int j=0; j<=min(i,m); ++j){
24             dp[i][j][0]=min(dp[i-1][j][0]+dis[c[i-1]][c[i]],dp[i-1][j][1]+p[i-1]*dis[d[i-1]][c[i]]+(1.0-p[i-1])*dis[c[i-1]][c[i]]);
25             if(j) dp[i][j][1]=min(dp[i-1][j-1][0]+p[i]*dis[c[i-1]][d[i]]+(1.0-p[i])*dis[c[i-1]][c[i]],dp[i-1][j-1][1]+p[i-1]*p[i]*dis[d[i-1]][d[i]]+p[i-1]*(1.0-p[i])*dis[d[i-1]][c[i]]+(1.0-p[i-1])*p[i]*dis[c[i-1]][d[i]]+(1.0-p[i-1])*(1.0-p[i])*dis[c[i-1]][c[i]]);
26         }
27     for(int i=0; i<=m; ++i) ans=min(ans,min(dp[n][i][0],dp[n][i][1]));
28     printf("%.2lf",ans); return 0;
29 }
壓行界的涼心
相關文章
相關標籤/搜索