NOIP2016 換教室 期望DP

傳送門

題解:
本蒟蒻第一次知道期望是啥意思。。很簡單,就是全部概率*價值求和
感覺期望差不多都和DP有關吧
dp[i][j][0/1]dp[i][j][0/1]表示選到第i節課,已經申請了換j節課,其中第i節選/不選的期望。

  • dp[i][j][0]={dp[i1][j][0]+dis[c[i1][c[i]]dp[i1][j][1]+dis[c[i1][c[i]](1k[i])+dis[d[i1]][c[i]]k[i] dp[i][j][0] = \left\{ \begin{array}{} dp[i - 1][j][0] + dis[c[i - 1][c[i]]\\ dp[i - 1][j][1] + dis[c[i - 1][c[i]] * (1 - k[i]) + dis[d[i - 1]][c[i]] * k[i]\\ \end{array} \right.
  • dp[i][j][1]={dp[i1][j][0]+dis[c[i1][c[i]]dp[i1][j][1]+dis[c[i1][c[i]](1k[i])+dis[d[i1]][c[i]]k[i] dp[i][j][1] = \left\{ \begin{array}{} dp[i - 1][j][0] + dis[c[i - 1][c[i]]\\ dp[i - 1][j][1] + dis[c[i - 1][c[i]] * (1 - k[i]) + dis[d[i - 1]][c[i]] * k[i]\\ \end{array} \right.
  • dp[i][j][1]={dp[i1][j1][0]+dis[c[i1]][d[i]]k[i]+dis[c[i1]][c[i]](1.0k[i])dp[i1][j1][1]+dis[d[i1]][d[i]]k[i1]k[i]+dis[d[i1]][c[i]]k[i1](1.0k[i])+dis[c[i1]][d[i]](1.0k[i1])k[i]+dis[c[i1]][c[i]](1.0k[i1])(1.0k[i]) dp[i][j][1] = \left\{ \begin{array}{} dp[i - 1][j - 1][0] + dis[c[i - 1]][d[i]] * k[i] + dis[c[i - 1]][c[i]] * (1.0 - k[i])\\ dp[i - 1][j - 1][1] + dis[d[i - 1]][d[i]] * k[i - 1] * k[i] + dis[d[i - 1]][c[i]] * k[i - 1] * (1.0 - k[i])\\ +dis[c[i - 1]][d[i]] * (1.0 - k[i - 1]) * k[i] + dis[c[i - 1]][c[i]] * (1.0 - k[i - 1]) * (1.0 - k[i]) \\ \end{array} \right.

dis用floyd處理一下即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 2001;

int c[MAXN], d[MAXN];
double k[MAXN];

int dis[301][301];
double dp[MAXN][MAXN][2];

inline int read(){
	int k = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
	return k * f;
}

int main(){
	memset(dp, 0x43, sizeof(dp));
	memset(dis, 0x3f, sizeof(dis));
	int n = read(), m = read(), N = read(), M = 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 <= N; i++){
		dis[i][i] = 0;
	}
	for(int i = 1; i <= M; i++){
		int a = read(), b = read(), l = read();
		dis[a][b] = dis[b][a] = min(dis[a][b], l);
	}
	
	for(int K = 1; K <= N; K++){
		for(int i = 1; i <= N; i++){
			for(int j = 1; j < i; j++){
				if(dis[i][j] > dis[i][K] + dis[K][j]){
					dis[i][j] = dis[j][i] = dis[i][K] + dis[K][j];
				}
			}
		}
	}
	dp[1][0][0] = dp[1][1][1] = 0;
	for(int i = 2; i <= n; i++){
		for(int j = 0; j <= min(i, m); j++){
			dp[i][j][0] = min(
				dp[i - 1][j][1] + (double)dis[c[i - 1]][c[i]] * (1.0 - k[i - 1])
							 	+ (double)dis[d[i - 1]][c[i]] * k[i - 1],
				dp[i - 1][j][0] + (double)dis[c[i - 1]][c[i]]
			);
			if(j){
				dp[i][j][1] = min(
					dp[i - 1][j - 1][0] + (double)dis[c[i - 1]][d[i]] * k[i]
										+ (double)dis[c[i - 1]][c[i]] * (1.0 - k[i]),
					dp[i - 1][j - 1][1] + (double)dis[d[i - 1]][d[i]] * k[i - 1] * k[i]
										+ (double)dis[d[i - 1]][c[i]] * k[i - 1] * (1.0 - k[i])
										+ (double)dis[c[i - 1]][d[i]] * (1.0 - k[i - 1]) * k[i]
										+ (double)dis[c[i - 1]][c[i]] * (1.0 - k[i - 1]) * (1.0 - k[i])
				);
			}

		}
	}
	
	double Ans = 2147483647;
	for(int i = 0; i <= m; i++){
		Ans = min(Ans, min(dp[n][i][0], dp[n][i][1]));
	}
	printf("%.2lf", Ans);
	return 0;
}
//dp[i][j][0/1] 第i節課,第j次機會換/不換
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章