[期望] Topcoder SRM561 Div1 1000. Orienteering

首先每条边至多走两遍,可以选出一条最长的链,这条链上的所有边走一遍,其他边走两边。

那么答案就是 2|E||P| 2 | E | − | P | 其中 E E 是边集,P 是最长的链

这个的期望就是 2E(|E|)E(|P|) 2 E ( | E | ) − E ( | P | )

E(|E|) E ( | E | ) 可以枚举每条边,求这条边存在的概率

E(|P|) E ( | P | ) 可以枚举点对,这对点对的距离乘上它为最长链的概率就是答案

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

const int N=310;

int n,m,k,cnt,G[N*10],sp[N*10],g[N][310];
struct edge{
  int t,nx;
}E[20*N];

inline void addedge(int x,int y){
  //cerr<<x<<' '<<y<<endl;
  E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
  E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt; 
}

vector<int> s;

int dis[2510][2510],sz[N*10],d[N][N];

void dfs(int x,int f,int s,int d){
  dis[s][x]=d;
  for(int i=G[x];i;i=E[i].nx)
    if(E[i].t!=f) dfs(E[i].t,x,s,d+1);
}

double ans;

inline double C(int x,int y,int kk=k){
  double ret=1;
  for(int i=0;i<kk;i++)
    ret=ret*(x-i)/(double)(y-i);
  return ret;
}

void pfs(int x,int f){
  sz[x]=sp[x];
  for(int i=G[x];i;i=E[i].nx)
    if(E[i].t!=f) pfs(E[i].t,x),sz[x]+=sz[E[i].t];
  if(f){
    int a=sz[x],b=m-a;
    double cur=0;
    if(a>=k) cur+=C(a,m);
    if(b>=k) cur+=C(b,m);
    ans+=1-cur;
  }
}

inline double EE(){
  pfs(1,0);
  return ans;
}

double c[N][N];

inline double PP(){
  double ret=0; int t=0;
  for(int i=0;i<s.size();i++)
    for(int j=0;j<s.size();j++)
      d[i][j]=dis[s[i]][s[j]];
  for(int i=0;i<s.size();i++)
    for(int j=i+1;j<s.size();j++){
      int cnt=0;
      for(int k=0;k<s.size();k++){
    if(k==i || k==j) continue;
    int flg=0;
    if(d[i][k]>d[i][j] || (d[i][k]==d[i][j] && k<j)) flg=1;
    if(d[j][k]>d[i][j] || (d[j][k]==d[i][j] && k<i)) flg=1;
    cnt+=flg;
      }
      cnt=m-cnt-2;
      if(cnt<k-2) continue;
      ret+=d[i][j]*c[cnt][k-2]/c[m][k];
    }
  //ret*=(m-k+1)*(m-k+2)/(double)k/(k-1);
  return ret;
}

class Orienteering{
public:
  double expectedLength(vector<string> field,int K){
    k=K;
    for(int i=0;i<field.size();i++) 
      for(int j=0;j<field[i].size();j++){
    if(field[i][j]=='#') continue;
    g[i][j]=++n;
    if(i && field[i-1][j]!='#') addedge(g[i-1][j],n);
    if(j && field[i][j-1]!='#') addedge(g[i][j-1],n);
    if(field[i][j]=='*') sp[n]=1,s.push_back(n);
      }
    m=s.size();
    for(int i=0;i<=m;i++){
      c[i][0]=1;
      for(int j=1;j<=i;j++)
    c[i][j]=c[i-1][j]+c[i-1][j-1];
    }
    for(int i=1;i<=n;i++) dfs(i,0,i,0);
    return 2*EE()-PP();
  }
}Main;

int main(){
  vector<string> f= {"**##*.**#..#.*...*#...*#..#.##..#..#.#*...#.##*##.",
 ".#..###..#..#.#.##..#.#.*#.*..#..#.#*..##.#*...*..",
 "..#.....###.#*.##..#.#.#*..#.#..#....#..#...#*####",
 ".#.##*#.*#..#*#*.#.#...*.#.*#.#.##.#*.##.#.#..*...",
 "..*.*#*.###.#..#.#..##.##.*#..#.....#.....#..#.#.#",
 ".#.##.#..##..*#..#.#...#*##*#*..#.#.#.#.##.##.#.#*",
 "..##....#..#.#*#...*.##...#.#.####...#.#*.....#...",
 ".#.*#.##.*#*.#*.#.#.#..#.#..#.#*#.###..##.##.#.##*",
 ".*.#*..*.#.#...#.*##.#.**.#.*...**..*#..#.#.#*.#..",
 ".#*.#*##....##.#.#*..*.###.#.##.##.#.#.#....#.#*.#",
 "*.#..#*#.#*#*....#.#.#..*#**...##.#.#.**#*##.*.#..",
 ".#*.##..##..##.#.#..#.#.###.###...#...#*#..##*#.#.",
 "#..#*.#..*.###..#.#...#.###.#.#*#.#.#**##.#...*.#*",
 "..#..#.#.##.#..#.**.##*#.#**.**..#.#..#...#.##*#..",
 ".#*#.#.*..#.*#...#.#...#...#.##.#..*#*.##*....###.",
 ".*.#.#.#.#*#..*##.**.##*##..#.*#.#*###..*.#.##.#..",
 ".#......#...#.#.*#.#.#..#..#.#*#....#*.#*#.*#..*.#",
 "#..####..#*#...#*.#..#.###...#.#.#.###*#..##*##.#.",
 ".#.*..#.#...#.#..#.##...#..#.#.#.#.###..##..*.*.*.",
 ".#.#.#.#..##.*..#.*.#.##.#..##*...#.#..#.#.##.#.##",
 ".#..#*.#.#..#.##..##..#.*..#.*#.#...##....#...###.",
 ".#.#.#.#*.#.#..#.#..#..#.#.*#...#.##...#.##.##.*..",
 ".#...#.#.##.#.#..*#.*#..###..#.#.#*###.##...#*.##.",
 ".#.##.*.......*.#.*#.#.#*###..*...*..#.*.##.#.#..#",
 "...###*####*#.#..##*...#..#..##.#.#.#..##*#*.*.*#.",
 "#.#.#....*#..#.#.#.#.##..#*.#...#..#.#*#...#.##.*.",
 "..*.#*##.#.#*#.###...#..##.#.#.#*###*#.*#.#.*###.#",
 "##*##..##...#.....##.#.#.**#..#*.....##.#..#*.#.*.",
 ".....#.*.##..##.##*.*#...#.#.#.##.#*#.**..#..#.#.#",
 "##.#.#*##.#.#.*.*.#.#*#.#.#....*...#*##*##.#....#.",
 "*.**#**....*..##.#*.*.**..##.###.##.....##...##.**",
 "#.####.##*#*##..#.*#*#.##*...#.##..#.##....#*..##.",
 "....#...##.#...#*.#..##.##.#*..*.#....##.#.*##...#",
 "#.#..*##*..#.#..#..#..#*....#.##..##.#*##.##.*##..",
 "..#.#*.*.##.#.#*#.#*##.###.##...#............#*.#.",
 "#.#.##.#....*....*..##..*#.#.#.###.#.#.#.###..#..#",
 ".#**..#*#.#*#*#.#.#...*##....##.#*..#..#*..*#..#..",
 "...#*#.....#..#.#..#*#.*##.#..#.#.##..#.*#*#.#...#",
 ".#*.###.#.#.#.#.*#*##.##..#.#*..#...#.#.#..#*.*#..",
 "#*.#.#.#..#..#..#....*#.*##..##.#.#..#...##.#.#..#",
 "*.#..#..#...#..##.#*#..#.#*#.#.#.###..#.#*...#.#..",
 "#...#.#...#.#.#..#.*.#*.....**.*..#*##.#*.##....##",
 "#*#....#*#..#.*.###*#..#*##.##.#.#...#.*.##.##.##.",
 "..##*##*..#*#.#..#*.*##*.##.#...#.#.#.#.#..*#.##..",
 "#...#*##.#*#**.##.*#.*.##..*.#*#**....#**##...*.*#",
 "*#.##......*#.##.#.#.##**.#.#.#.#.#.##..#...#*#*#*",
 "*....##.#.#..#.....#..##.#....*....#.#.##.#.#.##**",
 "#.##*#...#..#.#.##..#..##.##.##.##........##.#*#.#",
 "..#...#.#*#*..*#..*#.*#.#......##.#.#.#*#..#..****",
             ".###.#..#...#.#..#..#.#...#.#.#...**.#..*#*.*##*#."};
  int K=150;
  printf("%.9lf\n",Main.expectedLength(f,K));
  for(;;);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值