TC SRM 636 DIV1 500 ClosestRabbit

Problem Statement

有一个n*m的棋盘要放r个棋子,有些格子能放棋子,有些不能,每个棋子与其最近的棋子(如果有多个,优先取行数小的,仍有多个,优先取列数小的)建一条无向边,求期望连通块个数。

n,m≤20,2≤r≤n*m.

Tutorial

开始想往dp方向想,但状态定义不下。于是去挖性质。

n个点,n条边,如果是树边则连通块个数-1,如果是环边则不影响。

然后观察环(a-b,b-c,c-a),易证他们两两之间距离相等,又由最近点的定义,可得矛盾。

于是就知道了所有的环长度为2,换言之,一个环意味着一个两个点是彼此的最近点的点对。

还差一点:E(a+b+c+...+z)=E(a)+E(b)+...+E(z).

于是把每个点对出现概率加起来就好了。

 1 #include <vector>
 2 #include <list>
 3 #include <map>
 4 #include <set>
 5 #include <queue>
 6 #include <deque>
 7 #include <stack>
 8 #include <bitset>
 9 #include <algorithm>
10 #include <functional>
11 #include <numeric>
12 #include <utility>
13 #include <sstream>
14 #include <iostream>
15 #include <iomanip>
16 #include <cstdio>
17 #include <cmath>
18 #include <cstdlib>
19 #include <ctime>
20 #define inf (1<<30)
21 #define INF (1ll<<62)
22 #define fi first
23 #define se second
24 #define rep(x,s,t) for(register int x=s,t_=t;x<t_;++x)
25 #define per(x,s,t) for(register int x=t-1,s_=s;x>=s_;--x)
26 #define prt(x) cout<<#x<<":"<<x<<" "
27 #define prtn(x) cout<<#x<<":"<<x<<endl
28 #define pb(x) push_back(x)
29 #define hash asfmaljkg
30 #define rank asfjhgskjf
31 #define y1 asggnja
32 #define y2 slfvm
33 using namespace std;
34 typedef long long ll;
35 typedef pair<int,int> ii;
36 
37 template<class T>inline void Max(T &x,T y){if(x<y)x=y;}
38 template<class T>inline void Min(T &x,T y){if(x>y)x=y;}
39 
40 int n,m,tot;
41 const int maxc=405;
42 long double C[maxc][maxc];
43 
44 inline int calc(int x,int y){
45     return x*x+y*y;
46 }
47 
48 class ClosestRabbit {
49 public:
50     double getExpected(vector <string> d, int r) {
51         n=d.size();m=d[0].length();tot=0;
52         rep(i,0,n)rep(j,0,m)if(d[i][j]=='.')tot++;
53         rep(i,0,maxc){
54             rep(j,1,i)C[i][j]=C[i-1][j-1]+C[i-1][j];
55             C[i][0]=C[i][i]=1;
56         }
57         long double ans=0;
58         rep(i,0,n)rep(j,0,m)if(d[i][j]=='.')
59             rep(k,0,n)rep(l,0,m)if(d[k][l]=='.'){
60                 if(i==k&&j==l)continue;
61                 int cnt=0,dis=calc(i-k,j-l);
62                 rep(u,0,n)rep(v,0,m)if(d[u][v]=='.'){
63                     if(i==u&&j==v)continue;
64                     if(k==u&&l==v)continue;
65                     int t=1;
66                     int tmp=calc(i-u,j-v);
67                     if(tmp^dis)t&=tmp>dis;
68                     else if(u^k)t&=u>k;
69                     else if(v^l)t&=v>l;
70                     
71                     tmp=calc(k-u,l-v);
72                     if(tmp^dis)t&=tmp>dis;
73                     else if(u^i)t&=u>i;
74                     else if(v^j)t&=v>j;
75                     
76                     cnt+=t;
77                 }
78                 if(cnt>=r-2)ans+=C[cnt][r-2];
79             }
80         ans=ans/C[tot][r];ans=ans/2.0;
81         return ans;
82     }
83 };
View Code

 

posted @ 2016-08-10 16:37  ShinFeb  阅读(161)  评论(0编辑  收藏  举报