题解 P1850 [NOIP2016 提高组] 换教室

题解 P1850 [NOIP2016 提高组] 换教室

一.设置状态

(dp[i][j][k])表示走完前(i)个教室,换了(j)次,(k=1)表示上一次换教室了,(k=0)表示上一次没有换教室.

二.状态转移

(C1=c[i-1],D1=d[i-1],C2=c[i],D2=d[i])

考虑下列两种情况:

1. (k=0),不换

若上一次不换,则只能从C1转移到C2;

若上一次换了,则加上成功的期望和不成功的期望。

(dp[i][j][0]=minegin{cases}dp[i-1][j][0]+dis[C1][C2]\dp[i-1][j][1]+dis[D1][C2] imes k[i-1]+dis[C1][C2] imes (1-k[i-1])end{cases})

2. (k=1),换

若上一次不换,则加上这次成功和不成功的期望。

若上一次换,则

(mathfrak{(1)})上次成功,这次成功

(mathfrak{(2)})}上次成功,这次不成功

(mathfrak{(3)})上次不成功,这次成功

(mathfrak{(4)})上次不成功,这次不成功

(dp[i][j][1]=minegin{cases}dp[i-1][j-1][0]+dis[C1][D2] imes k[i]+dis[C1][C2] imes (1-k[i])\dp[i-1][j-1][1]+mathfrak{(1)}mp[D1][D2] imes k[i-1] imes k[i]+mathfrak{(2)}dis[D1][C2] imes k[i-1] imes (1-k[i])+mathfrak{(3)}dis[C1][D2] imes (1-k[i-1]) imes k[i]+mathfrak{(4)}dis[C1][C2] imes (1-k[i-1]) imes (1-k[i])end{cases})

三.最短路处理

简单的弗洛伊德Floyd三层循环

(Cade)

#include<bits/stdc++.h>
using namespace std;

const int N=2e3+7,M=3e2+7,INF=0x3f3f3f3f;
int n,m,v,e;
int c[N],d[N],dis[M][M];
double k[N],dp[N][N][2];

inline void read(int &x)
{
	char ch=getchar();x=0;
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
}

inline void Read()
{
	read(n),read(m),read(v),read(e);
	for(int i=1;i<=n;i++) read(c[i]);
	for(int i=1;i<=n;i++) read(d[i]);
	for(int i=1;i<=n;i++) scanf("%lf",&k[i]);
	for(int i=1;i<=v;i++)
		for(int j=1;j<i;j++)
			dis[i][j]=dis[j][i]=INF;
	for(int i=1,x,y,z;i<=e;i++)
	{
		read(x),read(y),read(z);
		dis[y][x]=dis[x][y]=min(dis[x][y],z);
	}
}

inline void Floyd()
{
	for(int k=1;k<=v;k++)
		for(int i=1;i<=v;i++)
			for(int j=1;j<i;j++)
				dis[j][i]=dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}

inline void Solve()
{
	for(int i=1;i<=n;i++)
		for(int j=0;j<=m;j++)
			dp[i][j][0]=dp[i][j][1]=INF;
	dp[1][0][0]=dp[1][1][1]=0;
	for(int i=2;i<=n;i++)
		for(int j=0;j<=m;j++)
		{
			dp[i][j][0]=min(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-1])+dis[d[i-1]][c[i]]*k[i-1]);
			if(j!=0)
				dp[i][j][1]=min(dp[i-1][j-1][0]+dis[c[i-1]][d[i]]*k[i]+dis[c[i-1]][c[i]]*(1-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-k[i])+dis[c[i-1]][d[i]]*(1-k[i-1])*k[i]+dis[c[i-1]][c[i]]*(1-k[i-1])*(1-k[i]));
		}
	double ans=INF;
	for(int i=0;i<=m;i++)
		for(int j=0;j<=1;j++)
			ans=min(ans,dp[n][i][j]);
	printf("%.2lf",ans);
}

int main()
{
	Read();
	Floyd();
	Solve();
	return 0;
}
原文地址:https://www.cnblogs.com/Sure042/p/tijie-p1850.html