题目链接
【题解】洛谷P1850[NOIP2016]换教室 期望DP+最短路
【题解】洛谷P1850[NOIP2016]换教室 期望DP+最短路
【题解】洛谷P1850[NOIP2016]换教室 期望DP+最短路
【题解】洛谷P1850[NOIP2016]换教室 期望DP+最短路
【题解】洛谷P1850[NOIP2016]换教室 期望DP+最短路


好久以前做的了

#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
const int N1=2010;
const int N2=310;
double dp[N1][N1][2];
//dp[i][j][0]表示前i个时间段用j次申请(第i个不申请)所需要的最小体力值
//dp[i][j][1]表示申请
double k[N1];//通过概率
int c[N1];//安排教室 
int d[N1];//另外教室 
int dis[N1][N1];//边权 
int main()
{
	//freopen("in.txt","r",stdin);
	int n,m,v,e,a,b;
	scanf("%d%d%d%d",&n,&m,&v,&e);//时间,申请,教室,道路 
	int i,j,l,w;//边权 
	for(i=1;i<=n;i++)
	scanf("%d",&c[i]);//安排 
	for(i=1;i<=n;i++)
	scanf("%d",&d[i]);//另外
	for(i=1;i<=n;i++)
	scanf("%lf",&k[i]);//概率
	memset(dis,127/2,sizeof(dis));
	for(i=1;i<=e;i++)
	{
		scanf("%d%d%d",&a,&b,&w);
		dis[a][b]=min(dis[a][b],w);
		dis[b][a]=min(dis[b][a],w);
	}
	for(i=1;i<=v;i++)dis[i][i]=0;
	for(l=1;l<=v;l++)
	for(i=1;i<=v;i++)
	for(j=1;j<=v;j++)
	if(dis[i][j]>dis[i][l]+dis[l][j])//处理最短路 
	dis[i][j]=dis[i][l]+dis[l][j];
	for(i=1;i<=v;i++)dis[0][i]=0;
	for(i=0;i<=2009;i++)
	for(j=0;j<=2009;j++)
	for(l=0;l<=1;l++)
	dp[i][j][l]=INF;
	//memset(dp,0x3f,sizeof(dp));
	dp[0][0][0]=0;
	for(i=0;i<=n-1;i++)
	for(j=0;j<=m;j++)
	{
		dp[i+1][j][0]=min(dp[i][j][0]+dis[c[i]][c[i+1]],dp[i][j][1]+dis[d[i]][c[i+1]]*k[i]+dis[c[i]][c[i+1]]*(1.0-k[i]));
		if(j!=m)dp[i+1][j+1][1]=min(dp[i][j][0]+dis[c[i]][d[i+1]]*k[i+1]+dis[c[i]][c[i+1]]*(1.0-k[i+1]),dp[i][j][1]+dis[c[i]][c[i+1]]*(1.0-k[i+1])*(1.0-k[i])+dis[d[i]][c[i+1]]*(1.0-k[i+1])*k[i]+dis[c[i]][d[i+1]]*k[i+1]*(1.0-k[i])+dis[d[i]][d[i+1]]*k[i]*k[i+1]);
	}
	double ans=INF;
	for(j=0;j<=m;j++)
	{
		ans=min(ans,min(dp[n][j][0],dp[n][j][1]));
	}
	printf("%.2lf\n",ans);
	return 0;
}

总结

相关文章: