MemberSRM470 Div1 500 DrawingLines
本番で解けなかった問題シリーズ.
問題
- 長方形の上辺と下辺にそれぞれn(≦10000)個の点が打ってある
- 上辺の点と下辺の点すべてを1対1でランダムで結ぶ
- 高々50個のペアは既に線が結んである
- 交差する線分のペアの数の期待値は?
解法
- 上辺の2点について,そこから引いた2本の線分が交差する確率を足す
- 選んだ2点の両方から既に線が引いてあるとき
- その線分が交わってれば確率1,交わってなければ確率0
- 片方からすでに線が引いてあるとき
- もう片方から,交わるように点を選ぶ確率を求める
- 両方の点についてまだ線が引かれていないとき
- 下辺の2点を選ぶと交差させるか,させないかの2通りなので確率0.5
- 選んだ2点の両方から既に線が引いてあるとき
- 頑張ればもうちょっと簡単な式で計算できるんだろうな・・・。
#include <iostream> #include <vector> using namespace std; class DrawingLines{ public: double countLineCrossings(int n, vector<int> startDot, vector<int> endDot){ int con[10000]; memset(con, -1, sizeof(con)); int ns = startDot.size(); for(int i=0;i<ns;i++) con[startDot[i]-1] = endDot[i]-1; double res = 0.0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ if(con[i]!=-1&&con[j]!=-1) res += (con[j]<con[i]); else if(con[i]!=-1||con[j]!=-1){ if(con[i]!=-1){ int cnt = con[i]; for(int k=0;k<ns;k++) cnt -= (endDot[k]-1 < con[i]); res += (double)cnt/(n-ns); } else { int cnt = n-con[j]-1; for(int k=0;k<ns;k++) cnt -= (endDot[k]-1 > con[j]); res += (double)cnt/(n-ns); } } else res += 0.5; } } return res; } };