【jzoj4905】【NOIP2016提高组】【†换教室】【动态规划】【期望】

题目大意

【jzoj4905】【NOIP2016提高组】【†换教室】【动态规划】【期望】_第1张图片

解题思路

先跑一次Floyd求出两点之间的距离,f[i][0,1]为第i个点申不申请到终点的期望,由于期望的线性性,和的期望等于期望和,所以可以很容易求出相邻两个点申不申请的期望,直接dp即可,具体可以看一下代码。

code

#include
#include
#include
#include
#define LD double
#define LL long long
#define max(x,y) ((x>y)?x:y)
#define min(x,y) ((x
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const maxn=2000,maxe=90000,maxv=300,inf=1e9;
int n,m,v,e,c[maxn+10],d[maxn+10],dis[maxv+10][maxv+10];
LD K[maxn+10],f[10][maxn+10][maxn+10],co[10][10],ans;
int main(){
    freopen("classroom.in","r",stdin);
    freopen("classroom.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&v,&e);
    fo(i,1,n)scanf("%d",&c[i]);
    fo(i,1,n)scanf("%d",&d[i]);
    fo(i,1,n)scanf("%lf",&K[i]);
    int a,b,w;
    fo(i,1,maxv)fo(j,1,maxv)dis[i][j]=inf;
    fo(i,1,maxv)dis[i][i]=0;
    fo(i,1,e){
        scanf("%d%d%d",&a,&b,&w);
        dis[a][b]=dis[b][a]=min(dis[a][b],w);
    }
    fo(k,1,maxv)
        fo(i,1,maxv)
            fo(j,1,maxv)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    fo(i,1,n)fo(j,0,m)fo(k,0,1)f[k][i][j]=inf;
    f[0][n][0]=f[1][n][1]=0;
    fd(i,n-1,1){
        co[0][0]=dis[c[i]][c[i+1]];
        co[1][0]=K[i]*dis[d[i]][c[i+1]]+(1-K[i])*dis[c[i]][c[i+1]];
        co[0][1]=K[i+1]*dis[c[i]][d[i+1]]+(1-K[i+1])*dis[c[i]][c[i+1]];
        co[1][1]=K[i]*K[i+1]*dis[d[i]][d[i+1]]+(1-K[i])*K[i+1]*dis[c[i]][d[i+1]]+
        K[i]*(1-K[i+1])*dis[d[i]][c[i+1]]+(1-K[i])*(1-K[i+1])*dis[c[i]][c[i+1]];
        fo(k,0,1)
            fo(j,k,m)
                fo(kk,0,1)
                    f[k][i][j]=min(f[k][i][j],co[k][kk]+f[kk][i+1][j-k]);
    }
    ans=inf;
    fo(k,0,1)
        fo(j,k,m)
            ans=min(ans,f[k][1][j]);
    printf("%.2lf",ans);
    return 0;
}

你可能感兴趣的:(动态规划,期望,bzoj)