换教室

换教室

有n个课程,第i个课程你在(c_i)教室上课,同时又有一堂课在(d_i),现在你可以提交m个申请,在第i个课程到(d_i)上课,成功概率(e_i),现在给出v
个教室教室的图,询问最小的路径期望,(1≤n≤2000,0≤m≤2000,1≤v≤300)

注意到点数很少,可以支持floyd,于是我们可以直接(O(n^3))预处理最短路,而显然为最优化问题,所以对阶段进行转移更好,于是设(f[i][j][0/1])表示到了第i个课程,已经申请了j个课程换教室,0表示当前课程换教室,反之,于是,设(s[x][y])为x,y间的最短路,不难有

[f[i][j][0]=min(f[i-1][j][0]+s[c[i]][c[i-1]],f[i-1][j][1]+ ]

[s[c[i]][c[i-1]](1-e[i-1])+s[c[i]][d[i-1]]e[i-1]) ]

[f[i][j][1]=min(f[i-1][j-1][0]+s[c[i]][c[i-1]](1-e[i])+s[d[i]][c[]i-1])e[i] ]

[,f[i-1][j-1][1]+s[c[i]][c[i-1]](1-e[i])(1-e[i-1])+s[c[i]][d[i-1]] ]

[(1-e[i-1])e[i]+s[d[i]][c[i-1]]e[i](1-e[i-1])+s[d[i]][d[i-1]] ]

[e[i]e[i-1]) ]

注意(igeq j),(f[1][0][0]=f[1][1][1]=0),其余全为无限大,答案在第一维的最后一层找即可。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#define il inline
#define ri register
using namespace std;
int c[2001],d[2001],dis[301][301];
double dp[2001][2001][2],ki[2001];
template<class free>il free Min(free,free);
int main(){
    int n,m,v,e,i,j,k;double ans(1e19);
    scanf("%d%d%d%d",&n,&m,&v,&e);
    for(i=1;i<=n;++i)scanf("%d",&c[i]);
    for(i=1;i<=n;++i)scanf("%d",&d[i]);
    for(i=1;i<=n;++i)scanf("%lf",&ki[i]);
    memset(dis,6,sizeof(dis));for(i=1;i<=v;++i)dis[i][i]=0;
    while(e--)scanf("%d%d%d",&i,&j,&k),dis[i][j]=dis[j][i]=min(dis[i][j],k);
    for(k=1;k<=v;++k)
        for(i=1;i<=v;++i)
            for(j=1;j<=v;++j)
                if(dis[i][k]+dis[k][j]<dis[i][j])
                    dis[i][j]=dis[i][k]+dis[k][j];
    memset(dp,66,sizeof(dp)),dp[1][0][0]=dp[1][1][1]=0;
    for(i=2;i<=n;++i){
        dp[i][0][0]=dp[i-1][0][0]+dis[c[i]][c[i-1]];
        for(j=1;j<=i&&j<=m;++j){
            dp[i][j][0]=Min(dp[i-1][j][0]+dis[c[i]][c[i-1]],
                            dp[i-1][j][1]+dis[c[i]][c[i-1]]*
                            (1-ki[i-1])+dis[c[i]][d[i-1]]*ki[i-1]);
            dp[i][j][1]=Min(dp[i-1][j-1][0]+dis[c[i]][c[i-1]]
                            *(1-ki[i])+dis[d[i]][c[i-1]]*ki[i],
                            dp[i-1][j-1][1]+dis[d[i]][d[i-1]]*ki[i]
                            *ki[i-1]+dis[d[i]][c[i-1]]*ki[i]*(1-ki[i-1])
                            +dis[c[i]][d[i-1]]*(1-ki[i])*ki[i-1]+
                            dis[c[i]][c[i-1]]*(1-ki[i])*(1-ki[i-1]));
        }
    }
    for(i=0;i<=m;++i)ans=Min(ans,Min(dp[n][i][0],dp[n][i][1]));
    printf("%.2lf",ans);
    return 0;
}
template<class free>
il free Min(free a,free b){
    return a<b?a:b;
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/10816910.html