您的位置:首页 > 其它

[NOIp2016提高组]换教室

2017-11-04 13:53 267 查看

题目大意:
  有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]));

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int inf=0x7fffffff;
const int N=2000,M=2001,V=301;
int c
,d
,dis[V][V];
double k
,f[2][M][2];
int main() {
int n=getint(),m=getint(),v=getint(),e=getint();
for(register int i=0;i<n;i++) c[i]=getint();
for(register int i=0;i<n;i++) d[i]=getint();
for(register int i=0;i<n;i++) scanf("%lf",&k[i]);
for(register int i=1;i<=v;i++) {
for(register int j=1;j<=v;j++) {
if(i!=j) dis[i][j]=inf;
}
}
for(register int i=0;i<e;i++) {
const int u=getint(),v=getint(),w=getint();
dis[u][v]=dis[v][u]=std::min(dis[u][v],w);
}
for(register int k=1;k<=v;k++) {
for(register int i=1;i<=v;i++) {
if(dis[i][k]==inf) continue;
for(register int j=1;j<=v;j++) {
if(dis[k][j]==inf) continue;
dis[i][j]=std::min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
for(register int j=0;j<=m;j++) {
f[0][j][0]=f[0][j][1]=1e9;
}
f[0][0][0]=f[0][1][1]=0;
for(register int i=1;i<n;i++) {
for(register int j=0;j<=m;j++) {
f[i&1][j][0]=f[i&1][j][1]=1e9;
}
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]);
for(register int j=1;j<=m;j++) {
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]);
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]));
}
}
double ans=1e9;
for(register int i=0;i<=m;i++) {
ans=std::min(ans,std::min(f[!(n&1)][i][0],f[!(n&1)][i][1]));
}
printf("%.2f\n",ans);
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: