[NOIP2016]换教室

题目:https://www.luogu.org/problemnew/show/P1850

noip中比较难的期望dp。首先要求出两两最短路,由于300个点90000条边直接选用floyd;

然后就是dp了:

dp[ i ][ j ][ 0/1 ]表示”第i天已经提出j次申请,其中第i天不换/换教室“状态下最小期望路程 。

转移方程比较长但是好推:

            dp[ i ][ 0 ][ 0 ] = dp[ i-1 ][ 0 ][ 0 ]+dis[ c[ i-1 ] ][ c[ i ] ];

            dp[i][j][0] = min(dp[i-1][j][0]+dis[c[i-1]][c[i]],dp[i-1][j][1]+dis[c[i-1]][c[i]]*(1.0-g[i-1])+dis[d[i-1]][c[i]]*g[i-1]);
            dp[i][j][1] = min(dp[i][j][1] , dp[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1.0-g[i])+dis[c[i-1]][d[i]]*g[i],dp[i-1][j-1][1]+dis[c[i-1]][c[i]]*(1.0-g[i-1])*(1.0-g[i])+dis[d[i-1]][c[i]]*g[i-1]*(1.0-g[i])+dis[c[i-1]][d[i]]*(1.0-g[i-1])*g[i]+dis[d[i-1]][d[i]]*g[i-1]*g[i]);
有一点长

注意(1.0 - g[ i ])不能写成(1 - g[ i ])。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 2050
#define V 305
int n,m,v,E;
int c[N],d[N],hed[V],cnt;
double dis[V][V];
double g[N],dp[N][N][2];
int main()
{
    scanf("%d%d%d%d",&n,&m,&v,&E);
    for(int i=1;i<=v;i++)
    {
        for(int j=1;j<=v;j++)
        {
            if(i!=j)dis[i][j]=1e12+5.0;
        }
    }
    for(int i=1;i<=n;i++)
        scanf("%d",&c[i]);
    for(int i=1;i<=n;i++)
        scanf("%d",&d[i]);
    for(int i=1;i<=n;i++)
        scanf("%lf",&g[i]);
    for(int f,t,w,i=1;i<=E;i++)
    {
        scanf("%d%d%d",&f,&t,&w);
        dis[f][t]=min(dis[f][t],(double)w);
        dis[t][f]=min(dis[t][f],(double)w);
    }
    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]);
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
            dp[i][j][0]=dp[i][j][1]=1e12+5.0;
    dp[1][0][0]=dp[1][1][1]=0.0;
    for(int i=2;i<=n;i++)
    {
        dp[i][0][0] = dp[i-1][0][0] + dis[c[i-1]][c[i]];
        for(int j=1;j<=i&&j<=m;j++)
        {
            dp[i][j][0] = min(dp[i-1][j][0]+dis[c[i-1]][c[i]],dp[i-1][j][1]+dis[c[i-1]][c[i]]*(1.0-g[i-1])+dis[d[i-1]][c[i]]*g[i-1]);
            dp[i][j][1] = min(dp[i][j][1] , dp[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1.0-g[i])+dis[c[i-1]][d[i]]*g[i]);
            dp[i][j][1] = min(dp[i][j][1] , dp[i-1][j-1][1]+dis[c[i-1]][c[i]]*(1.0-g[i-1])*(1.0-g[i])+dis[d[i-1]][c[i]]*g[i-1]*(1.0-g[i])+dis[c[i-1]][d[i]]*(1.0-g[i-1])*g[i]+dis[d[i-1]][d[i]]*g[i-1]*g[i]);
        }
    }
    double ans = 1e12;
    for(int i=0;i<=m;i++)
        ans = min(ans,min(dp[n][i][0],dp[n][i][1]));
    printf("%.2lf
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9744364.html