#概率、数学期望,动态规划#洛谷 1850 换教室

题目


分析

d p [ n ] [ m ] [ 0 / 1 ] dp[n][m][0/1] dp[n][m][0/1]表示前 n n n个时间段共申请 m m m次时该时间段申不申请换教室的最短路径,方程显然


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,nn,t,now[2001],tur[2001],dis[301][301];
double  k[2001],dp[2][2001][2];
inline signed iut(){
     rr int ans=0; rr char c=getchar();
     while (!isdigit(c)) c=getchar();
     while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
     return ans;                        
}
signed main(){
    n=iut (); m=iut(); nn=iut(); t=iut();
    memset(dis,127/3,sizeof(dis));
    for (rr int i=1;i<=n;++i) now[i]=iut();
    for (rr int i=1;i<=n;++i) tur[i]=iut();
    for (rr int i=1;i<=n;++i) scanf("%lf",&k[i]);
    for (;t;--t){
        rr int x=iut(),y=iut(),w=iut();
        dis[x][y]=dis[y][x]=min(dis[x][y],w);
    }
    for (rr int k=1;k<=nn;++k)
    for (rr int i=1;i<=nn;++i)
    for (rr int j=1;j<=nn;++j) if (i!=j&&i!=k&&j!=k)
        dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    for (rr int i=1;i<=nn;++i)
        dis[i][0]=dis[0][i]=dis[i][i]=0;
    for (rr int i=0;i<=m;++i) dp[1][i][0]=dp[1][i][1]=dis[0][0];
    dp[1][0][0]=dp[1][1][1]=0;
    for (rr int i=2;i<=n;++i){
        for (rr int j=0;j<=m;++j) dp[i&1][j][0]=dp[i&1][j][1]=dis[0][0];
        rr int tt=min(i,m); dp[i&1][0][0]=dp[(i&1)^1][0][0]+dis[now[i-1]][now[i]];
        for (rr int j=1;j<=tt;++j){
            dp[i&1][j][0]=min(dp[(i&1)^1][j][0]+dis[now[i-1]][now[i]],dp[(i&1)^1][j][1]+k[i-1]*dis[tur[i-1]][now[i]]+(1-k[i-1])*dis[now[i-1]][now[i]]);
            dp[i&1][j][1]=min(dp[(i&1)^1][j-1][0]+dis[now[i-1]][tur[i]]*k[i]+dis[now[i-1]][now[i]]*(1-k[i]),dp[(i&1)^1][j-1][1]+k[i-1]*k[i]*dis[tur[i-1]][tur[i]]+k[i-1]*(1-k[i])*dis[tur[i-1]][now[i]]+(1-k[i-1])*k[i]*dis[now[i-1]][tur[i]]+(1-k[i-1])*(1-k[i])*dis[now[i-1]][now[i]]);
        }
    }
    rr double ans=1e18;
    for (rr int i=0;i<=m;++i)
        ans=min(ans,min(dp[n&1][i][0],dp[n&1][i][1]));
    return !printf("%.2lf",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值