【題解】NOIP2016換教室
阿新 • • 發佈:2018-02-21
its 事件 統計 blog sin 方式 || 選擇 +=
哇好開心啊!寫的時候真的全然對於這個加法沒有把握,但還是大著膽子試著寫了一下——竟然過了樣例?於是又調了一下就過啦。
不過想想也覺得是正確的吧,互相獨立的事件對於期望的影響自然也是相互獨立的,可以把所有的情況看成一個整體,不同的統計方式只是分組的區別,最後算出來的答案肯定是一樣的。dp的狀態比較顯然:dp[i][j][0/1]代表當前在第i節課,已經用去了j次申請的機會,0/1分別代表當前這一節課是否申請。那麽這個時候就分情況討論,計算這一次的選擇對於答案的影響。
這些不同的情況分別是:當前和上一次是否選擇申請換課,申請換課的是否成功。
期望的計算式:成功的概率*成功的代價+失敗的概率*失敗的代價。
#include <bits/stdc++.h> usingnamespace std; #define maxn 2050 #define INF 1047483640 #define maxm 2050 #define maxv 400 int n, m, v, e, dis[maxv][maxv], c[maxn], d[maxn]; double ans = 9999999, dp[maxn][maxm][2], k[maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); } while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar(); return x * k; } void init() { for(int i = 1; i <= v; i ++) for(int j = i + 1; j <= v; j ++) dis[i][j] = dis[j][i] = INF; for(int i = 1; i <= n; i ++)for(int j = 0; j <= m; j ++) dp[i][j][0] = dp[i][j][1] = INF; } double gmin(double &x, double y) { x = (x < y) ? x : y; } int gmin2(int &x, int y) { x = (x < y) ? x : y; } void Floyd() { for(int k = 1; k <= v; k ++) for(int i = 1; i <= v; i ++) for(int j = 1; j <= v; j ++) gmin2(dis[i][j], dis[i][k] + dis[k][j]); } int main() { n = read(), m = read(), v= read(), e = read(); for(int i = 1; i <= n; i ++) c[i] = read(); for(int i = 1; i <= n; i ++) d[i] = read(); init(); dp[0][0][0] = dp[0][0][1] = 0; for(int i = 1; i <= n; i ++) scanf("%lf", &k[i]); for(int i = 1; i <= e; i ++) { int x = read(), y = read(), z = read(); dis[x][y] = dis[y][x] = min(dis[y][x], z); } for(int i = 1; i <= v; i ++) dis[i][i] = 0; Floyd(); for(int i = 1; i <= v; i ++) dis[i][0] = dis[0][i] = 0; c[0] = d[0] = 0, k[0] = 1; for(int i = 1; i <= n; i ++) for(int j = 0; j <= m; j ++) { gmin(dp[i][j][0], dp[i - 1][j][0] + dis[c[i]][c[i - 1]]); gmin(dp[i][j][0], dp[i - 1][j][1] + dis[c[i]][c[i - 1]] * (1 - k[i - 1]) + dis[c[i]][d[i - 1]] * k[i - 1]); if(j) gmin(dp[i][j][1], dp[i - 1][j - 1][0] + dis[c[i]][c[i - 1]] * (1 - k[i]) + dis[d[i]][c[i - 1]] * k[i]); double tem = 0; tem += dis[c[i]][c[i - 1]] * (1 - k[i]) * (1 - k[i - 1]); tem += dis[c[i]][d[i - 1]] * (1 - k[i]) * k[i - 1]; tem += dis[d[i]][c[i - 1]] * k[i] * (1 - k[i - 1]); tem += dis[d[i]][d[i - 1]] * k[i] * k[i - 1]; if(j) gmin(dp[i][j][1], dp[i - 1][j - 1][1] + tem); } for(int i = 0; i <= m; i ++) gmin(ans, min(dp[n][i][0], dp[n][i][1])); printf("%.2lf", ans); return 0; }
【題解】NOIP2016換教室