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 };