BZOJ4720-Change classroom

The question is very long. It is a probability dp question. Generally, it needs to be reversed, but the ending of this question is uncertain, so it must be pushed forward.

Use f[i][j][k], i represents the i-th period, j represents the application for j times, and k represents whether the application is used in this round. 

Then require min(f[n][0~m][0],f[n][0~m][1])

The state transition equation is a bit cumbersome and requires care.

① No application is required for the previous one, and no application is required for the current time. This is the easiest to deduce f[i][j][0]=min(f[i][j][0], (f[i-1][j][0]+dis[c[i-1 ]][c[i]]))×1.0)

②Currently j>=1, then you can apply at least once. That is, if you did not apply at the previous time, you can apply now. Or applied at the previous time, but did not apply now.

③The current j>=2, then you can consider applying for it some time ago. Because applications are divided into successes and failures, there are 4 different situations to consider. They are:

successful application -> successful application

Application successful -> application failed

Application failed -> application successful

Application failed -> Application failed

The _11s in the code means that I applied for it some time ago, and I applied this time, and the application was successful. 1 means applied, 0 means not applied. s means success, f means failure.

code show as below:

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long ll;

int n,m,v,e;
int c[2333],d[2333];
double k[2333];
int dis[333][333],a,b,cc;
double f[2333][2333][2];
int  main(){
    scanf("%d%d%d%d",&n,&m,&v,&e);
    for(int i=1;i<=n;++i)scanf("%d",&c[i]);
    for(int i=1;i<=n;++i)scanf("%d",&d[i]);
    for(int i=1;i<=n;++i)scanf("%lf",&k[i]);
    memset(dis,0x3f,sizeof dis);
    for(int i=1;i<=v;++i)dis[i][i]=0;
    for(int i=1;i<=e;++i){
        scanf("%d%d%d",&a,&b,&cc);
        dis[a][b]=dis[b][a]=min(dis[a][b],cc);
    }
    for(int kk=1;kk<=v;++kk)
        for(int i=1;i<=v;++i)
            for(int j=1;j<=v;++j)
                dis[i][j]=dis[j][i]=min(dis[i][j],dis[i][kk]+dis[kk][j]);
    for(int i=0;i<=n;++i)for(int j=0;j<=m;++j)
        f[i][j][0]=f[i][j][1]=0x3f3f3f3f;
    f[1][0][0]=f[1][1][1]=0.0;
    for(int i=2;i<=n;++i){
        for(int j=0;j<=min(i,m);++j){
            f[i][j][0]=min(f[i][j][0],f[i-1][j][0]+dis[c[i-1]][c[i]]);
            if(j>=1){
                double _10s=(f[i-1][j][1]+1.0*dis[d[i-1]][c[i]])*k[i-1];
                double _10f=(f[i-1][j][1]+1.0*dis[c[i-1]][c[i]])*(1.0-k[i-1]);
                f[i][j][0]=min(f[i][j][0],_10s+_10f);
                double _01s=(f[i-1][j-1][0]+1.0*dis[c[i-1]][d[i]])*k[i];
                double _01f=(f[i-1][j-1][0]+1.0*dis[c[i-1]][c[i]])*(1.0-k[i]);
                f[i][j][1]=min(f[i][j][1],_01s+_01f);
            }
            if(j>=2){
                double _11ss,_11ff,_11sf,_11fs;
                _11ss=(f[i-1][j-1][1]+dis[d[i-1]][d[i]])*k[i-1]*k[i];
                _11ff=(f[i-1][j-1][1]+1.0*dis[c[i-1]][c[i]])*(1.0-k[i-1])*(1.0-k[i]);
                _11fs=(f[i-1][j-1][1]+1.0*dis[c[i-1]][d[i]])*(1.0-k[i-1])*k[i];
                _11sf=(f[i-1][j-1][1]+1.0*dis[d[i-1]][c[i]])*k[i-1]*(1.0-k[i]);
                double tmp=_11ss+_11ff+_11sf+_11fs;
                f[i][j][1]=min(f[i][j][1],tmp);
            }
        }
    }
    double ans=0x3f3f3f3f;
    for(int i=0;i<=m;++i)
        ans = min (ans, min (f [n] [i] [ 0 ], f [n] [i] [ 1 ]));
    printf("%.2lf\n",ans);
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325224661&siteId=291194637