BZOJ4720

我能说这道题我想到了思路交上去只有44分,结果发现程序各种小错误,唉。。。

其实就是一个裸的概率Dp+floyed

就是转移方程烦了一点,不过也很容易想到。

用f[i][j][k]来表示前i节课选j个来换当前这节课是否要换。

具体的就看程序吧。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxx 1000000000.0
#define maxn 2009
using namespace std;
int n,m,c,e;
int a[maxn][2],u1,u2,v1,v2;
double d1,d2,d3,d4,g[maxn][maxn],b[maxn],f[maxn][maxn][2];
int main()
{
  scanf("%d%d%d%d",&n,&m,&c,&e);
  for (int j=0;j<=1;j++)
  for (int i=1;i<=n;i++) 
  scanf("%d",&a[i][j]);
  for (int i=1;i<=n;i++) scanf("%lf",&b[i]);
  for (int i=0;i<=c;i++)
  for (int j=0;j<=c;j++)
  if (i!=j) g[i][j]=maxx;
  
  int x,y,xx;
  for (int i=1;i<=e;i++)
  {
      scanf("%d%d%d",&x,&y,&xx);
      g[x][y]=min((double)xx,g[x][y]);
      g[y][x]=g[x][y];
  }
  for (int k=0;k<=c;k++)
  for (int i=0;i<=c;i++)
  for (int j=0;j<=c;j++)
  g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
  
  for (int i=0;i<=n;i++)
  for (int j=0;j<=m;j++)
  for (int k=0;k<2;k++)
  f[i][j][k]=maxx;
  
  f[1][0][0]=0;
  f[1][1][1]=0;
  for (int i=2;i<=n;i++)
  {
      u1=a[i][0];u2=a[i][1];v1=a[i-1][0];v2=a[i-1][1];
  for (int j=0;j<=min(m,i);j++)
  {
   f[i][j][0]=f[i-1][j][0]+g[u1][v1];
   if (j>0)
   {
   f[i][j][1]=f[i-1][j-1][0]+g[u1][v1]*(1-b[i])+g[u2][v1]*b[i];
   f[i][j][0]=min(f[i-1][j][1]+g[u1][v1]*(1-b[i-1])+g[u1][v2]*b[i-1],
   f[i][j][0]);
   d1=g[u1][v1]*(1-b[i-1])*(1-b[i]);
   d2=g[u1][v2]*(1-b[i])*b[i-1];
   d3=g[u2][v1]*b[i]*(1-b[i-1]);
   d4=g[u2][v2]*b[i]*b[i-1];
   f[i][j][1]=min(f[i][j][1],f[i-1][j-1][1]+d1+d2+d3+d4);
   }
  }
  }
  double ans=f[n][0][0];
  for (int i=0;i<=m;i++) ans=min(min(ans,f[n][i][0]),f[n][i][1]);
  printf("%.2lf
",ans);
  return 0;
}
原文地址:https://www.cnblogs.com/2014nhc/p/7656692.html