概率DP 换教室

传送门:http://cogs.pro/cogs/problem/problem.php?pid=2558

       教室数很小,路又很多,考虑用floyd.(开始把k打里面了,颜面扫地。。)

       因为只能提交m个,所以数组就是三维,f[i][j][0/1].i表示第几节课,j表示到i时选了多少节,第三维表示i是否选

       既然提交后不知道能否通过,所以期望要分类讨论(废话)一共四种情况,也就是i选没选,i-1选没选,

       r1(原来的),r2(换后的)。

       分别写一下吧,

       i-1不选,i不选,f[i][j][0]=f[i-1][j][0]+dis[r1[i-1]][r1[i]];

       i-1选,i不选,      f[i][j][0]=f[i-1][j][1]+luck[i-1]*dis[r2[i-1]][r1[i]];

       i-1不选,i 选 ,     类似。

       i-1,i均选          讨论四种,两个概率相乘。

      打的时候,觉得从零开始很别扭,就初始化出了1的

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 2000
using namespace std;
int n,m,v,e,r1[N+5],r2[N+5],dis[305][305];
int fa[N+5];
double luck[N+5],f[N+5][N+5][2],unluck[N+5];
void init()
{
	memset(dis,0x3f,sizeof(dis));
	scanf("%d%d%d%d",&n,&m,&v,&e);
	for(int i=1;i<=n;i++)
	   for(int j=0;j<=m;j++)
	       f[i][j][0]=f[i][j][1]=1e18;
	for(int i=1;i<=n;i++)
	   scanf("%d",&r1[i]);
	for(int i=1;i<=n;i++)
	   scanf("%d",&r2[i]);
	for(int i=1;i<=n;i++)
	   scanf("%lf",&luck[i]),unluck[i]=1-luck[i];
	int x,y,z;
	for(int i=1;i<=e;i++)
	{
		scanf("%d%d%d",&x,&y,&z);
	    dis[x][y]=min(dis[x][y],z);
	    dis[y][x]=dis[x][y];
	}   
}
int yjn()
{
	//freopen("classrooma.in","r",stdin);
	//freopen("classrooma.out","w",stdout);
	init();
	for(int i=1;i<=v;i++)dis[i][i]=0;
	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!=i&&k!=j)
			     dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
	
	f[1][0][0]=f[1][1][1]=0.0;
	for(int i=1;i<n;i++)
	   for(int j=0;j<=m;j++)
	   {
	   	    f[i+1][j][0]=min(f[i+1][j][0],f[i][j][0]+dis[r1[i]][r1[i+1]]);
	   	    f[i+1][j][0]=min(f[i+1][j][0],f[i][j][1]+luck[i]*dis[r2[i]][r1[i+1]]+unluck[i]*dis[r1[i]][r1[i+1]]);
	   	    if(j<m)
	   		{
				f[i+1][j+1][1]=min(f[i+1][j+1][1],f[i][j][0]+luck[i+1]*dis[r1[i]][r2[i+1]]+unluck[i+1]*dis[r1[i]][r1[i+1]]);
	   	        f[i+1][j+1][1]=min(f[i+1][j+1][1],f[i][j][1]+luck[i]*unluck[i+1]*dis[r2[i]][r1[i+1]]+unluck[i]*unluck[i+1]*dis[r1[i]][r1[i+1]]+unluck[i]*luck[i+1]*dis[r1[i]][r2[i+1]]+luck[i]*luck[i+1]*dis[r2[i]][r2[i+1]]);
	  		}
	   }
	double s=1e18;
	for(int i=0;i<=m;i++)
	   s=min(s,min(f[n][i][0],f[n][i][1]));
	printf("%0.2lf",s);
}
int qty=yjn();
int main(){;}





   
posted @ 2017-10-06 20:19  Hzoi_QTY  阅读(152)  评论(0编辑  收藏  举报