noip2016換教室(期望dp)
阿新 • • 發佈:2018-11-08
整體思路:
這節課換了教室的期望路程 = min(上節課換了教室的期望路程 + 上節課教室到這節課教室的期望路程, 上節課沒換教室的期望路程+ 上節課教室到這節課教室的期望路程)
這節課沒換教室的期望路程 = min(上節課換了教室的期望路程 + 上節課教室到這節課教室的期望路程,上節課沒換教室的期望路程+ 上節課教室到這節課教室的期望路程)
上節課教室到這節課教室的期望路程 = 某一情況路程 * 這一情況發生的概率;
dp[i][j][0/1]第i節課換了j次這節課換或不換
細節:
初值,邊界,
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int n, m, v, e,c[2005],d[2005],bian[2005][2005]; double k[2005],f[2005][2005][2],ans = 1e18; int main() { cin >> 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(bian,0x3f3f3f3f3f,sizeof(bian)); for(int i = 1; i <= e; i++) { int x, y, w; scanf("%d%d%d", &x, &y, &w); bian[x][y] = min(w, bian[x][y]); bian[y][x] = bian[x][y]; } for(int i = 1; i <= v; i++) bian[i][i] = 0; for(int e = 1; e <= v; e++) for(int i = 1; i <= v; i++) for(int j = 1; j <= v; j++) bian[i][j] = min(bian[i][j],bian[i][e] + bian[e][j]); for(int i = 1; i <= n; i++) for(int j = 0; j <= m; j++) { f[i][j][0] = f[i][j][1] = 1e30; } f[1][0][0] = f[1][1][1] = 0; for(int i = 2; i <= n; i++) { int ha = min(i , m); for(int j = 0; j <= ha; j++) { f[i][j][0] = min(f[i][j][0], f[i-1][j][0] + bian[c[i-1]][c[i]]); f[i][j][0] = min(f[i][j][0], f[i-1][j][1] + bian[d[i-1]][c[i]] *k[i - 1] + bian[c[i-1]][c[i]] * (1.0 - k[i - 1])); if(j >= 1) { f[i][j][1] = min(f[i-1][j-1][0] + bian[c[i-1]][d[i]] * k[i] + bian[c[i -1]][c[i]] * (1.0 - k[i]),f[i][j][1]); f[i][j][1] = min(f[i][j][1],f[i-1][j-1][1] + bian[d[i-1]][d[i]] * k[i] * k[i-1] + bian[d[i-1]][c[i]] * k[i - 1] * (1.0 - k[i]) + bian[c[i-1]][d[i]] *(1.0 - k[i-1])*k[i] + bian[c[i-1]][c[i]] * (1.0 - k[i]) *(1.0 - k[i-1])); } } } for(int i = 0; i <= m; i++) { double t = min(f[n][i][0] , f[n][i][1]); ans = min(ans, t); } printf("%0.2lf", ans); return 0; }