洛谷P1850 换教室

大力dp,先floyd处理每个点之间的最短路,然后大力dp就行了

代码

//By AcerMo
#include
#include
#include
#include
#include
using namespace std;
const int M=3050;
int n,m,v,e;
int fr[M],se[M];
double p[M],f[M][M][2],map[M][M];
inline int read()
{
    int x=0;char ch=getchar();
    while (ch>'9'||ch<'0') ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;	
} 
signed main()
{
    n=read();m=read();v=read();e=read();
    for (int i=1;i<=n;i++) fr[i]=read();
    for (int i=1;i<=n;i++) se[i]=read();
    for (int i=1;i<=n;i++) scanf("%lf",&p[i]);
    for (int i=1;i<=v;i++)
    for (int k=1;k<=v;k++)
    map[i][k]=2e9*1.0;
    for (int i=1;i<=e;i++)
    {
        int x=read(),y=read(),z=read();
        map[x][y]=map[y][x]=min(map[x][y],(double)z);
    }
    for (int k=1;k<=v;k++)
    for (int i=1;i<=v;i++)
    for (int j=1;j<=v;j++)
    map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
    for (int i=1;i<=v;i++) 
    map[i][i]=map[i][0]=map[0][i]=0;
    for (int i=1;i<=n;i++)
    for (int k=0;k<=m;k++)
    f[i][k][0]=f[i][k][1]=2e9*1.0;
    f[1][0][0]=f[1][1][1]=0.0;
    for (int i=2;i<=n;i++)
    for (int k=0;k<=min(m,i);k++)
    {
        f[i][k][0]=min(f[i-1][k][0]+map[fr[i-1]][fr[i]],f[i-1][k][1]+map[fr[i-1]][fr[i]]*(1.0-p[i-1])+map[se[i-1]][fr[i]]*p[i-1]);
        if (k>0)
        {
            f[i][k][1]=min(f[i-1][k-1][0]+map[fr[i-1]][se[i]]*p[i]+map[fr[i-1]][fr[i]]*(1.0-p[i]),           
            f[i-1][k-1][1]+map[se[i-1]][se[i]]*p[i-1]*p[i]+map[se[i-1]][fr[i]]*p[i-1]*(1.0-p[i])+               
            map[fr[i-1]][se[i]]*(1.0-p[i-1])*p[i]+map[fr[i-1]][fr[i]]*(1.0-p[i-1])*(1.0-p[i]));       
        }
    }
    double ans=2e9*1.0;
    for (int i=0;i<=m;i++) 
    ans=min(ans,min(f[n][i][0],f[n][i][1]));
    printf("%.2lf",ans);
    return 0;
}

 

你可能感兴趣的:(动态规划)