【NOIP2016换教室】概率DP
本题由于算法比较显然,直接写出算法
Luogu 1850
本题概率DP,
状态 f[i][j][1/0]前i门课选择了j门要处理换,第i门决定要换的到达状态期望距离
初始化:f[1][1][1]=f[1][0][0]=0,别的f设inf ,对图上的所有两点进行floyd
由于我们知道对于一个状态是从哪个地方转化过来增加距离只与i和i-1的概率有关(失败或成功要从哪个结点转向另外哪一个点有距离*概率的和为其转化状态的期望)
然后对于f[i][j][0]有
min {
f[i-1][j][0] + dis(i-1 0 到 i 0)
f[i-1][j][1] + dis(i-1 0 到 i 0)*(1-k[i-1]) + dis(i-1 1 到 i 0)*(k[i-1])
} 这里的i-1 0 和 i 0 就是 c[0]和 d[0] ,即从哪个变量的成功或失败后的位置,失败为 0 ,成功为 1
然后对于f[i][j][1]
min
{
f[i-1][j-1][0] + dis(i-1 0到 i 0)*(1-k[i]) + dis(i-1 0 到 i 1)*k[i]
f[i-1][j-1][1] + dis(i-1 0 到 i 0)*(1-k[i-1])*(1-k[i]) + dis(i-1 0 到 i 1)*(1-k[i-1])*k[i]+ dis(i-1 1 到 i 0)*k[i-1]*(1-k[i]) + dis(i-1 1 到 i 1)*k[i-1]*k[i]
}
最后答案在f[n][1->m][0\1]中找就可以了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int n,m,v,e; int dis[305][305]; double f[2005][2005][2]; int c[2005],d[2005]; double k[2005]; 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]); for(int i=1;i<=v;i++) { for(int j=1;j<=v;j++) { dis[i][j]=0x3f3f3f3f; } dis[i][i]=0; } for(int i=1;i<=e;i++) { int a,b,w; scanf("%d%d%d",&a,&b,&w); if(w<dis[a][b]) { dis[a][b]=dis[b][a]=w; } } for(int o=1;o<=v;o++) { for(int i=1;i<=v;i++) { for(int j=1;j<=v;j++) { dis[i][j] = min(dis[i][j],dis[i][o]+dis[o][j]); } } } for(int i=0;i<=n;i++) { for(int j=0;j<=m;j++) f[i][j][0]=f[i][j][1]=1e9; } f[1][1][1]=f[1][0][0]=0; for(int i=2;i<=n;i++) { for(int j=0;j<=m;j++) { int xx0=c[i-1]; int xx1=d[i-1]; int yy0 = c[i]; int yy1 = d[i]; double kk0 = k[i-1]; double kk1 = k[i]; f[i][j][0]=min(f[i-1][j][0]+dis[xx0][yy0],f[i-1][j][1]+dis[xx1][yy0]*kk0+dis[xx0][yy0]*(1.0-kk0)); if(j>0) f[i][j][1]=min( f[i-1][j-1][0] + dis[xx0][yy0]*(1-kk1) + dis[xx0][yy1]*kk1,f[i-1][j-1][1] + dis[xx0][yy0]*(1-kk0)*(1-kk1) + dis[xx0][yy1]*(1-kk0)*kk1 + dis[xx1][yy0]*kk0*(1-kk1) + dis[xx1][yy1]*kk0*kk1 ); } } double ans = 1e9; for(int i=0;i<=m;i++) { ans = min(ans,f[n][i][0]); ans = min(ans,f[n][i][1]); } printf("%.2lf",ans); }