• [NOIp2016提高组]换教室


    题目大意:
      有n节课,第i节课在c[i]上课,同时d[i]也有一节课d[i]。
      你有权利向教务处发出m次申请把自己的教室改到d[i],相应的批准概率是k[i]。
      教室是图上的一些点,其中每条边都有边权。
      问你上完所有课走的总路程的期望。

    思路:
      动态规划。
      f[i][j][0/1]表示上了i个课,换了j次教室,这门课有没有换教室。
      转移方程为:
      f[i][j][0]=min(f[i-1][j][0]+dis[c[i-1]][c[i]],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
      f[i][j][1]=min(f[i-1][j-1][0]+dis[c[i-1]][d[i]]*k[i]+dis[c[i-1]][c[i]]*(1-k[i]),f[i-1][j-1][1]+dis[d[i-1]][d[i]]*k[i-1]*k[i]+dis[d[i-1]][c[i]]*k[i-1]*(1-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i]));

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x;
    10 }
    11 const int inf=0x7fffffff;
    12 const int N=2000,M=2001,V=301;
    13 int c[N],d[N],dis[V][V];
    14 double k[N],f[2][M][2];
    15 int main() {
    16     int n=getint(),m=getint(),v=getint(),e=getint();
    17     for(register int i=0;i<n;i++) c[i]=getint();
    18     for(register int i=0;i<n;i++) d[i]=getint();
    19     for(register int i=0;i<n;i++) scanf("%lf",&k[i]);
    20     for(register int i=1;i<=v;i++) {
    21         for(register int j=1;j<=v;j++) {
    22             if(i!=j) dis[i][j]=inf;
    23         }
    24     }
    25     for(register int i=0;i<e;i++) {
    26         const int u=getint(),v=getint(),w=getint();
    27         dis[u][v]=dis[v][u]=std::min(dis[u][v],w);
    28     }
    29     for(register int k=1;k<=v;k++) {
    30         for(register int i=1;i<=v;i++) {
    31             if(dis[i][k]==inf) continue;
    32             for(register int j=1;j<=v;j++) {
    33                 if(dis[k][j]==inf) continue;
    34                 dis[i][j]=std::min(dis[i][j],dis[i][k]+dis[k][j]);
    35             }
    36         }
    37     }
    38     for(register int j=0;j<=m;j++) {
    39         f[0][j][0]=f[0][j][1]=1e9;
    40     }
    41     f[0][0][0]=f[0][1][1]=0;
    42     for(register int i=1;i<n;i++) {
    43         for(register int j=0;j<=m;j++) {
    44             f[i&1][j][0]=f[i&1][j][1]=1e9;
    45         }
    46         f[i&1][0][0]=std::min(f[!(i&1)][0][0]+dis[c[i-1]][c[i]],f[!(i&1)][0][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
    47         for(register int j=1;j<=m;j++) {
    48             f[i&1][j][0]=std::min(f[!(i&1)][j][0]+dis[c[i-1]][c[i]],f[!(i&1)][j][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
    49             f[i&1][j][1]=std::min(f[!(i&1)][j-1][0]+dis[c[i-1]][d[i]]*k[i]+dis[c[i-1]][c[i]]*(1-k[i]),f[!(i&1)][j-1][1]+dis[d[i-1]][d[i]]*k[i-1]*k[i]+dis[d[i-1]][c[i]]*k[i-1]*(1-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i]));
    50         }
    51     }
    52     double ans=1e9;
    53     for(register int i=0;i<=m;i++) {
    54         ans=std::min(ans,std::min(f[!(n&1)][i][0],f[!(n&1)][i][1]));
    55     }
    56     printf("%.2f
    ",ans);
    57     return 0;
    58 }
  • 相关阅读:
    c语言字符串_续
    c语言中文件的操作
    Linux基础知识
    netstat
    wireshark 过滤规则
    常用cmd命令
    优化过的redis封装类
    二十三岁,新的起点
    计划看的书目
    [转载]爱上一个给予你正能量的人
  • 原文地址:https://www.cnblogs.com/skylee03/p/7783190.html
Copyright © 2020-2023  润新知