【題解】LuoGu1850:換教室

原題傳送門
期望dp
狀態:dpi,j,0/1dp_{i,j,0/1}表示到第ii個時間點,共計請求jj次,當前這一個時間點是否請求的答案
預處理:v<=300v<=300直接floydfloyd預處理最短路
轉移:
dpi,j,0=min(dpi1,j,0+wci1,ci,dpi1,j,1+wci1,ci(1ki1)+wdi1,ciki)dp_{i,j,0}=min(dp_{i-1,j,0}+w_{c_{i-1},{c_i}},dp_{i-1,j,1}+w_{c_{i-1},c_i}*(1-k_{i-1})+w_{d_{i-1},c_i}*k_i)
dpi,j,1=min(dpi1,j1,0+wci1,ci(1ki)+wci1,diki,dpi1,j1,1+wci1,ci(1ki1)(1ki)+wci1,di(1ki1)ki+wdi1,ci1ki1(1ki)+wdi1,diki1ki)dp_{i,j,1}=min(dp_{i-1,j-1,0}+w_{c_{i-1},c_i}*(1-k_i)+w_{c_{i-1},d_i}*k_i,dp_{i-1,j-1,1}+w_{c_{i-1},c_i}*(1-k_{i-1})*(1-k_i)+w_{c_{i-1},d_i}*(1-k_{i-1})*k_i+w_{d_{i-1},c_{i-1}}*k_{i-1}*(1-k_i)+w_{d_{i-1},d_i}*k_{i-1}*k_i)

Code:

#include <bits/stdc++.h>
#define maxn 2010
using namespace std;
double dp[maxn][maxn][2], k[maxn];
int n, m, v, e, c[maxn], d[maxn], w[maxn][maxn];

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

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();
	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) w[i][j] = 1e9;
	for (int i = 1; i <= e; ++i){
		int x = read(), y = read(), z = read();
		w[x][y] = min(w[x][y], z), w[y][x] = w[x][y];
	}
	for (int k = 1; k <= v; ++k)
		for (int i = 1; i <= v; ++i)
			if (i != k)
			for (int j = 1; j <= v; ++j)
				if (j != k && i != j)
					w[i][j] = min(w[i][j], w[i][k] + w[k][j]);
	for (int i = 0; i <= n; ++i)
		for (int j = 0; j <= m; ++j) dp[i][j][0] = dp[i][j][1] = 1e9;
	dp[1][0][0] = dp[1][1][1] = 0;
	for (int i = 2; i <= n; ++i){
		dp[i][0][0] = dp[i - 1][0][0] + w[c[i - 1]][c[i]];
		for (int j = 1; j <= min(m, i); ++j){
			int A = c[i - 1], B = d[i - 1], C = c[i], D = d[i];
			dp[i][j][0] = min(dp[i - 1][j][0] + w[A][C], dp[i - 1][j][1] + w[A][C] * (1 - k[i - 1]) + w[B][C] * k[i - 1]),
			dp[i][j][1] = min(dp[i - 1][j - 1][0] + w[A][C] * (1 - k[i]) + w[A][D] * k[i],
			 dp[i - 1][j - 1][1] + w[A][C] * (1 - k[i - 1]) * (1 - k[i]) + w[B][C] * k[i - 1] * (1 - k[i]) + w[A][D] * (1 - k[i - 1]) * k[i] + w[B][D] * k[i - 1] * k[i]);
		}
	}
	double ans = 1e9;
	for (int i = 0; i <= m; ++i) ans = min(ans, min(dp[n][i][0], dp[n][i][1]));
	printf("%.2lf\n", ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章