发布于 

【NOIP2016】换教室 题解

NOIP2016

核心思路

dpi,j,0/1dp_{i,j,0/1}表示前ii个教室,提交了jj个申请,第ii个教室是否成功的最小期望体力。

disi,j\mathrm{dis}_{i,j}表示从iijj的最短距离,Floyd初始化。

下面是完整的转移方程。

dpi,j,0=min{dpi1,j,0+disci1,cidpi1,j,1+(1ki1)disci1,ci+ki1disdi1,cidpi,j,1=min{dpi1,j1,0+disci1,ci(1ki)+disci1,dikidpi1,j1,1+disdi1,dikiki1+disdi1,ciki1(1ki)+disci1,di(1ki1)ki+disci1,ci(1ki)(1ki1)\begin{aligned} dp_{i,j,0}&=\min\begin{cases}dp_{i-1,j,0}+dis_{c_{i-1},c_i}\\dp_{i-1,j,1}+(1-k_{i-1})dis_{c_{i-1},c_i}+k_{i-1}dis_{d_{i-1,c_i}}\end{cases} \\ dp_{i,j,1}&=\min\begin{cases} dp_{i-1,j-1,0}+dis_{c_{i-1},c_i}(1-k_i)+dis_{c_{i-1},d_i}k_i\\dp_{i-1,j-1,1}+dis_{d_{i-1},d_i}k_ik_{i-1}+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-k_{i-1})\end{cases} \end{aligned}

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define int ll
#define REP(i,e,s) for(register int i=e; i<=s; i++)
#define DREP(i,e,s) for(register int i=e; i>=s; i--)
#define ll long long
#define DE(...) fprintf(stderr,__VA_ARGS__)
#define DEBUG(a) DE("DEBUG: %d\n",a)
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
int read() {
int x=0,f=1,ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}

const int MAXN=2000+10,INF=0x3f3f3f;

int c[MAXN],d[MAXN],a[MAXN][MAXN];
double dp[MAXN][MAXN][2],k[MAXN];

signed main() {
int n=read(),m=read(),v=read(),e=read();
REP(i,1,n) c[i]=read();
REP(i,1,n) d[i]=read();
REP(i,1,n) scanf("%lf",&k[i]);

REP(i,0,v) REP(j,0,v) a[i][j]=INF;
REP(i,1,v) a[i][i]=a[i][0]=a[0][i]=0;

REP(i,1,e) {
int x=read(),y=read(),w=read();
a[x][y]=a[y][x]=min(a[x][y],w);
}

REP(t,1,v) REP(i,1,v) REP(j,1,v) a[i][j]=min(a[i][j],a[i][t]+a[t][j]);
REP(i,0,n) REP(j,0,m) dp[i][j][0]=dp[i][j][1]=INF;

dp[1][0][0]=dp[1][1][1]=0;
DE("in");
REP(i,2,n) {
dp[i][0][0]=dp[i-1][0][0]+a[c[i-1]][c[i]];
REP(j,1,min(i,m)) {
dp[i][j][0]=min(dp[i-1][j][0]+a[c[i-1]][c[i]],dp[i-1][j][1]+a[c[i-1]][c[i]]*(1-k[i-1])+a[d[i-1]][c[i]]*k[i-1]);
dp[i][j][1]=min(dp[i-1][j-1][0]+a[c[i-1]][c[i]]*(1-k[i])+a[c[i-1]][d[i]]*k[i],
dp[i-1][j-1][1]+a[d[i-1]][d[i]]*k[i]*k[i-1]+a[d[i-1]][c[i]]*k[i-1]*(1-k[i])+a[c[i-1]][d[i]]*(1-k[i-1])*k[i]+a[c[i-1]][c[i]]*(1-k[i])*(1-k[i-1]));
}
}


double ans=INF;

REP(i,0,m) DE("%.2lf\n",ans=min(ans,min(dp[n][i][1],dp[n][i][0])));
printf("%.2lf\n",ans);
return 0;
}