NOIP2016 换教室 期望DP

版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82083960

传送门

题解:
本蒟蒻第一次知道期望是啥意思。。很简单,就是全部概率*价值求和
感觉期望差不多都和DP有关吧
d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] 表示选到第i节课,已经申请了换j节课,其中第i节选/不选的期望。

  • d p [ i ] [ j ] [ 0 ] = { d p [ i 1 ] [ j ] [ 0 ] + d i s [ c [ i 1 ] [ c [ i ] ] d p [ i 1 ] [ j ] [ 1 ] + d i s [ c [ i 1 ] [ c [ i ] ] ( 1 k [ i ] ) + d i s [ d [ i 1 ] ] [ 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.
  • d p [ i ] [ j ] [ 1 ] = { d p [ i 1 ] [ j ] [ 0 ] + d i s [ c [ i 1 ] [ c [ i ] ] d p [ i 1 ] [ j ] [ 1 ] + d i s [ c [ i 1 ] [ c [ i ] ] ( 1 k [ i ] ) + d i s [ d [ i 1 ] ] [ 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.
  • d p [ i ] [ j ] [ 1 ] = { d p [ i 1 ] [ j 1 ] [ 0 ] + d i s [ c [ i 1 ] ] [ d [ i ] ] k [ i ] + d i s [ c [ i 1 ] ] [ c [ i ] ] ( 1.0 k [ i ] ) d p [ i 1 ] [ j 1 ] [ 1 ] + d i s [ d [ i 1 ] ] [ d [ i ] ] k [ i 1 ] k [ i ] + d i s [ d [ i 1 ] ] [ c [ i ] ] k [ i 1 ] ( 1.0 k [ i ] ) + d i s [ c [ i 1 ] ] [ d [ i ] ] ( 1.0 k [ i 1 ] ) k [ i ] + d i s [ c [ i 1 ] ] [ c [ i ] ] ( 1.0 k [ i 1 ] ) ( 1.0 k [ 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次机会换/不换

猜你喜欢

转载自blog.csdn.net/DyingShu/article/details/82083960