zoukankan      html  css  js  c++  java
  • Noip2016 换教室(数学期望入门)

    题意:有2n个课程安排在n个时间段上,在第i个时间被安排在ci教室上课,但牛牛可以申请换教室,到di教室上课,但只有pi的可能成功。学校有v个教室,e条道路,每条路双向连通,每条路都会消耗一定的体力wi(保证每个教室可以互相到达),问牛牛应该怎么安排,才能使总花费的体力的期望值最小。

    输入格式:

    第一行四个整数n,m,v,e。n表示时间短的数量;m表示最多可以申请更换教室的数量;v表示教室的数量;e表示道路的数量。

    第二行n个正整数,第i个表示ci;

    第三行n个正整数,第i个表示di;

    第四行n个实数,第i个表示pi;

    接下来e行,每行三个正整数ai,bi,wi,表示,有一条双向道路连通ai与bi,消耗的体力为wi;

    保证输入的实数最多包含三位小数。

    输出格式:

    输出一行,包含一个实数,四舍五入到小数点后两位,表示答案。

    输入样例:

    3 2 3 3
    2 1 2
    1 2 1
    0.8 0.2 0.5
    1 2 5
    1 3 3
    2 3 1

    输出样例:

    2.80

    解析:一道数学期望的入门题,dp的方程不难想,dp[i][j][k] 表示前i个教室,换了j次教室,第i个点有没有换所走的最小期望距离。显然 dp[i][j][0] = max(dp[i-1][j][0] + 所需的代价, dp[i-1][j][1] + 所需的代价),dp[i][j][1] = max(dp[i-1][j-1][0] + 所需的代价, dp[i-1][j-1][1] + 所需的代价)。本题的关键便在“所需的代价”上(状态转移特别毒瘤)。转移如下:

    dp[i][j][0] = max(dp[i-1][j][0] + 上一个教室与这一个教室的距离, dp[i-1][j][1] + 上一次换教室与这一次的距离*上次换教室成功的几率 + 上一次没换教室与这一次的距离*上一次换教室不成功的几率);

    dp[i][j][1] = max(dp[i-1][j-1][0] + 上一个教室与这个教室换了教室的距离*这个教室换成功的几率 + 上一个教室与这个教室的距离*这个教室换不成功的几率, dp[i-1][j-1][1] + 上一个教室换了与这个教室换了的距离*上个教室换成功的几率*这个教室换成功的几率 + 上一个教室与这个教室的距离*上个教室换不成功的几率*这个教室换不成功的几率 + 上一个教室换了与这个教室的距离*上个教室换成功的几率*这个教室换不成功的几率 + 上个教室与这个教室换了的距离*上个教室换不成功的几率*这个教室换成功的几率);

    注意:换教室成功的几率为pi, 则不成功的几率则为(1-pi)。

    转移特别麻烦,而且也特别长。

    代码如下:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 
     5 int n,m,v,e,w[301][301],c[2001],d[2001];
     6 double p[2001],dp[2001][2001][2],ans=2e9;
     7 
     8 void floyd(void) {  //floyd预处理每个教室之间的距离 
     9     for (int k=1;k<=v;++k)
    10       for (int i=1;i<=v;++i)
    11         for (int j=1;j<=v;++j) 
    12           w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
    13 }
    14 
    15 int main() {
    16     scanf("%d%d%d%d",&n,&m,&v,&e);
    17       for (int i=1;i<=n;++i) scanf("%d",&c[i]);
    18       for (int i=1;i<=n;++i) scanf("%d",&d[i]);
    19       for (int i=1;i<=n;++i) scanf("%lf",&p[i]);
    20       for (int i=1;i<=v;++i)
    21         for (int j=1;j<i;++j) w[i][j]=w[j][i]=1e9;
    22       for (int i=1;i<=e;++i) {
    23           int x,y,v; scanf("%d%d%d",&x,&y,&v);
    24           w[x][y]=w[y][x]=min(w[x][y],v);  //处理重边 
    25       }
    26     floyd();
    27       for (int i=1;i<=n;++i) 
    28         for (int j=0;j<=m;++j) dp[i][j][1]=dp[i][j][0]=1e9;
    29     dp[1][0][0]=dp[1][1][1]=0;  //dp初始化 
    30       for (int i=2;i<=n;++i)
    31         for (int j=0;j<=min(i,m);++j) {  //恶心的转移 
    32           dp[i][j][0]=min(dp[i][j][0],min(dp[i-1][j][0]+w[c[i-1]][c[i]],dp[i-1][j][1]+w[d[i-1]][c[i]]*p[i-1]+w[c[i-1]][c[i]]*(1-p[i-1])));
    33           if (j>0) dp[i][j][1]=min(dp[i][j][1],min(dp[i-1][j-1][0]+w[c[i-1]][d[i]]*p[i]+w[c[i-1]][c[i]]*(1-p[i]),dp[i-1][j-1][1]+w[d[i-1]][d[i]]*p[i-1]*p[i]+w[c[i-1]][c[i]]*(1-p[i-1])*(1-p[i])+w[c[i-1]][d[i]]*(1-p[i-1])*p[i]+w[d[i-1]][c[i]]*p[i-1]*(1-p[i])));
    34         }
    35       for (int i=0;i<=m;++i) ans=min(ans,min(dp[n][i][1],dp[n][i][0]));  //不一定要用完所有换教室的机会,所以取min 
    36     printf("%.2lf",ans);
    37     return 0;
    38 }
  • 相关阅读:
    Apache的Order Allow,Deny 详解
    apache的AllowOverride以及Options使用详解
    安装启动apache2.4后报Invalid command 'order', perhaps misspelled or defined by a module not included
    前端常见跨域解决方案(全)
    php面试宝典
    php面试题2018
    nginx负载均衡的5种策略
    多台服务器共享session问题
    小程序定义并使用类
    微信小程序真机预览接口不到数据,打开调试确能请求到
  • 原文地址:https://www.cnblogs.com/Gaxc/p/9507211.html
Copyright © 2011-2022 走看看