版权声明:转载请注明原出处啦QAQ(虽然应该也没人转载): https://blog.csdn.net/hzk_cpp/article/details/83062422
题目:luogu1850.
题目大意:给定v个教室,教室之间有e条无向边边,保证连通.现在有n组教室,每组有一个被钦定的教室和一个可以替换的教室,现在给你m次替换教室的机会,以及当你打算替换掉一组教室时成功的概率,让你求最后依次经过你选择的教室的期望路径最小值.
我觉得我的题目大意好像解释得不是很清晰...
模拟赛考真题的时候由于我没有写过概率DP,然后一直调这道题调了3h,导致T2部分分一点都没拿...
现在突然发现自己列的状态貌似不太主流,然后写的方式又细节极多,而且还是在我迷了很久期望的定义的情况写的...
我们现在来详解这道题.
首先我在考场列的状态是f[i][j][k]表示到第i个时段,用掉了j次机会,是否成功换掉了第j组教室的期望.
这个状态实际上是错误的,因为这个状态它已知是否申请成功,而题目上说是一次性提交的,说明不知道是否申请成功.
然后我们会发现这个东西列出方程后细节比较多,我们换一种转态.
我们依然设状态f[i][j][k],但这是k表示的是否申请去换地j组教室.
那么容易列出方程:
扫描二维码关注公众号,回复:
3618996 查看本文章
当i=j=0时是要特殊处理的,j>0时f[i][j][1]时没有意义的,所以要判断.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=2000,V=300,INF=1<<29;
int dis[V+9][V+9];
int c[N+9],d[N+9];
double k[N+9],f[N+9][N+9][2],ans=INF*1.0;
int n,m,v,e;
void floyd(){
for (int k=1;k<=v;k++)
for (int i=1;i<=v;i++)
for (int j=1;j<=v;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
Abigail into(){
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]);
for (int i=1;i<=v;i++)
for (int j=1;j<=v;j++)
if (i^j) dis[i][j]=INF;
int x,y,z;
for (int i=1;i<=e;i++){
scanf("%d%d%d",&x,&y,&z);
if (dis[x][y]<=z) continue;
dis[x][y]=dis[y][x]=z;
}
}
Abigail work(){
floyd();
for (int i=0;i<=n;i++)
for (int j=0;j<=m;j++)
f[i][j][0]=f[i][j][1]=INF*1.0;
f[1][0][0]=0;f[1][1][1]=0;
for (int i=2;i<=n;i++){
f[i][0][0]=f[i-1][0][0]+dis[c[i-1]][c[i]];
for (int j=1;j<=m;j++){
f[i][j][0]=min(f[i][j][0],f[i-1][j][0]+dis[c[i-1]][c[i]]);
f[i][j][0]=min(f[i][j][0],f[i-1][j][1]+dis[c[i-1]][c[i]]*(1-k[i-1])+dis[d[i-1]][c[i]]*k[i-1]);
if (j>0) f[i][j][1]=min(f[i][j][1],f[i-1][j-1][0]+dis[c[i-1]][c[i]]*(1-k[i])+dis[c[i-1]][d[i]]*k[i]);
if (j>0) f[i][j][1]=min(f[i][j][1],f[i-1][j-1][1]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]+dis[d[i-1]][c[i]]*k[i-1]*(1-k[i])+dis[d[i-1]][d[i]]*k[i-1]*k[i]);
}
}
for (int i=0;i<=m;i++)
ans=min(ans,min(f[n][i][0],f[n][i][1]));
}
Abigail outo(){
printf("%.2lf\n",ans);
}
int main(){
into();
work();
outo();
return 0;
}