bzoj 1415

莫名互测题...

这题一看就是期望dp,可是不会转移,所以考试写50分暴力走人...

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Edge
{
  int next;
  int to;
}edge[2005];
int head[1005];
int dis[1005][1005];
bool used[1005];
int cnt=1;
int n,m;
int p0,p1;
void init()
{
  memset(head,-1,sizeof(head));
  cnt=1;
}
void add(int l,int r)
{
  edge[cnt].next=head[l];
  edge[cnt].to=r;
  head[l]=cnt++;
}
void spfa(int rt)
{
  queue <int> M;
  memset(dis[rt],0x3f,sizeof(dis[rt]));
  memset(used,0,sizeof(used));
  dis[rt][rt]=0;
  used[rt]=1;
  M.push(rt);
  while(!M.empty())
    {
      int u=M.front();
      M.pop();
      for(int i=head[u];i!=-1;i=edge[i].next)
	{
	  int to=edge[i].to;
	  if(dis[rt][to]>dis[rt][u]+1)
	    {
	      dis[rt][to]=dis[rt][u]+1;
	      if(!used[to])
		{
		  used[to]=1;
		  M.push(to);
		}
	    }
	}
    }
}
double ans=0;
void dfs(double p,int v,int pr,int pz)
{
  if(pr==pz)
    {
      ans+=(double)v*p;
      return;
    }
  int maxp=0;
  int temp=0x3f3f3f3f;
  for(int i=head[pr];i!=-1;i=edge[i].next)
    {
      int to=edge[i].to;
      if(dis[to][pz]<temp)
	{
	  temp=dis[to][pz];
	  maxp=to;
	}else if(dis[to][pz]==temp)
	{
	  maxp=min(maxp,to);
	}
    }
  pr=maxp;
  if(pr==pz)
    {
      ans+=(double)v*p;
      return;
    }
  maxp=0;
  temp=0x3f3f3f3f;
  for(int i=head[pr];i!=-1;i=edge[i].next)
    {
      int to=edge[i].to;
      if(dis[to][pz]<temp)
	{
	  temp=dis[to][pz];
	  maxp=to;
	}else if(dis[to][pz]==temp)
	{
	  maxp=min(maxp,to);
	}
    }
  pr=maxp;
  if(pr==pz)
    {
      ans+=(double)v*p;
      return;
    }
  int cot=0;
  for(int i=head[pz];i!=-1;i=edge[i].next)
    {
      cot++;
    }
  cot++;
  for(int i=head[pz];i!=-1;i=edge[i].next)
    {
      int to=edge[i].to;
      if(to==pr)
	{
	  ans+=(double)p*(double)1.0/(double)cot*(double)v;
	  continue;
	}
      dfs(p*(double)1.0/(double)cot,v+1,pr,to);
    }
  dfs(p*(double)1.0/(double)cot,v+1,pr,pz);
}
int main()
{
// freopen("eat.in","r",stdin);
//  freopen("eat.out","w",stdout);
  scanf("%d%d",&n,&m);
  scanf("%d%d",&p0,&p1);
  if(p0==p1)
    {
      printf("0\n");
      return 0;
    }
  init();
  for(int i=1;i<=m;i++)
    {
      int x,y;
      scanf("%d%d",&x,&y);
      add(x,y);
      add(y,x);
    }
  for(int i=1;i<=n;i++)
    {
      spfa(i);
    }
  dfs(1,1,p0,p1);
  printf("%.3lf\n",ans);
  return 0;
}

正解:期望dp+记忆华搜索 

设状态f[i][j]代表聪聪在i点,可可在j点时聪聪追上可可的期望

然后用dfs更新即可,注意先预处理出最短路和tpos[i][j]表示聪聪在i点,可可在j点时聪聪走一步时会走到的位置

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Edge
{
    int next;
    int to;
}edge[2005];
int head[1005];
int cnt=1;
int dis[1005][1005];
int tpos[1005][1005];
double f[1005][1005];
bool used[1005];
int inr[1005];
int n,m,p0,p1;
void add(int l,int r)
{
    edge[cnt].next=head[l];
    edge[cnt].to=r;
    head[l]=cnt++;
}
void bfs(int rt)
{
    queue <int> M;
    memset(used,0,sizeof(used));
    memset(dis[rt],0x3f,sizeof(dis[rt]));
    M.push(rt);
    dis[rt][rt]=0;
    used[rt]=1;
    while(!M.empty())
    {
        int u=M.front();
        M.pop();
        for(int i=head[u];i;i=edge[i].next)
        {
            int to=edge[i].to;
            if(used[to])
            {
                continue;
            }
            used[to]=1;
            dis[rt][to]=dis[rt][u]+1;
            M.push(to);
        }
    }
}
double dfs(int pr,int pz)
{
    if(f[pr][pz]!=-1.0)
    {
        return f[pr][pz];
    }
    if(pr==pz)
    {
        return f[pr][pz]=0.0;
    }
    if(tpos[pr][pz]==pz)
    {
        return f[pr][pz]=1.0;
    }
    if(tpos[tpos[pr][pz]][pz]==pz)
    {
        return f[pr][pz]=1.0;
    }
    f[pr][pz]=0.0;
    for(int i=head[pz];i;i=edge[i].next)
    {
        int to=edge[i].to;
        f[pr][pz]+=dfs(tpos[tpos[pr][pz]][pz],to);
    }
    f[pr][pz]=(f[pr][pz]+dfs(tpos[tpos[pr][pz]][pz],pz))/(double)inr[pz]+1;
    return f[pr][pz];
}
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int main()
{
//	freopen("eat.in","r",stdin);
//	freopen("eat.out","w",stdout);
    n=read(),m=read();
    p0=read(),p1=read();
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        add(x,y);
        add(y,x);
        inr[x]++;
        inr[y]++;
    }
    for(int i=1;i<=n;i++)
    {
        inr[i]++;
        bfs(i);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            f[i][j]=-1.0;
            int temp=0x3f3f3f3f;
            for(int k=head[i];k;k=edge[k].next)
            {
                int to=edge[k].to;
                if(dis[to][j]<temp)
                {
                    tpos[i][j]=to;
                    temp=dis[to][j];
                }else if(dis[to][j]==temp)
                {
                    tpos[i][j]=min(tpos[i][j],to);
                }
            }		
        }
    }
    printf("%.3lf\n",dfs(p0,p1));
    return 0;
}

 

posted @ 2018-10-05 08:38  lleozhang  Views(74)  Comments(0Edit  收藏  举报
levels of contents