• NOIP2016换教室


    Description

    Click here

    Analysis

    不得不承认看了题之后确实想到的是概率dp。。。

    由于博主太懒而且这篇题解挺详细

    我就只记录一下没讲到的地方


     

    f[i][j][1/0]是上了i节课,当前换了j次(包括本节课)教室的本节课的选择(0/1)

    只给f[1][1][1],[1][0][0]两项赋初值为0

    强调一下f[i][j][k]是已经上了i节课,换了j次教室(包括第i节课),这节课是否换教室

    所以只有上第一节课换教室(f[1][1][1])和不换教室(f[1][0][0])两种情况要初始化且初始化为0

    注意循环中j=0要分开

    代码

    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int INF=800000000;
    int n,m,v,e;
    int c[2005],d[2005],dis[305][305];
    double k[2005],f[2005][2005][2];
    inline int read(){
    	int x=0;char ch=getchar();
    	while(ch<'0'||ch>'9')ch=getchar();
    	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;
    }
    int main(){
        scanf("%d%d%d%d",&n,&m,&v,&e);
        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++)cin>>k[i];
        for (int i=1;i<=v;i++)
            for (int j=1;j<i;j++)
                dis[j][i]=dis[i][j]=INF;
        for(int i=1;i<=e;i++){
            int cn=read(),cm=read(),cw=read();
            dis[cn][cm]=dis[cm][cn]=min(dis[cn][cm],cw);
        }
        //输入
        for(int l=1;l<=v;l++){
            for(int i=1;i<=v;i++){
                for(int j=1;j<i;j++){
                    if(dis[i][j]>dis[i][l]+dis[l][j])
                    dis[j][i]=dis[i][j]=dis[i][l]+dis[l][j];
                }
            }
        }
        //Floyd
        for(int i=1;i<=n;i++){
            for(int j=0;j<=m;j++){
                f[i][j][0]=f[i][j][1]=INF;
            }
        }
        f[1][1][1]=f[1][0][0]=0;
        for (int i=2;i<=n;i++)
            for (int j=0;j<=m;j++){
                f[i][j][0]= min(f[i-1][j][1]+ k[i-1]*dis[d[i-1]][c[i]]+ (1-k[i-1])*dis[c[i-1]][c[i]], 
                                f[i-1][j][0] +dis[c[i-1]][c[i]]);
                if (j!=0)
                    f[i][j][1]=min(f[i-1][j-1][1]+k[i-1]*k[i]*dis[d[i-1]][d[i]]+k[i-1]*(1-k[i])*dis[d[i-1]][c[i]]+(1-k[i-1])*k[i]*dis[c[i-1]][d[i]]+(1-k[i-1])*(1-k[i])*dis[c[i-1]][c[i]],
                                f[i-1][j-1][0]+k[i]*dis[c[i-1]][d[i]]+(1-k[i])*dis[c[i-1]][c[i]]);
            }
        //dp
        double ans=INF;
        for (int i=0;i<=m;i++)
            for (int j=0;j<=1;j++){
                ans=min(ans,f[n][i][j]);
            }
        printf("%.2lf",ans);
        return 0;
    }
    
  • 相关阅读:
    .NET面试题目
    ASP.NET应用管理系统框架概述(三)
    ASP.NET应用管理系统框架概述(二)
    ASP.NET应用管理系统框架概述(一)
    InstallShield使用文档
    dotnet的安装包例子
    Access数据库连接池
    InstallShield使用——InstallScript MIS Project例子
    InstallShield使用——例子
    ASP.NET针对Sybase数据库使用分页技术
  • 原文地址:https://www.cnblogs.com/lqhsr/p/10828221.html
Copyright © 2020-2023  润新知