【隨機算法】(NWERC2014) F-Finding Lines

題目描述

給n個點,求是否至少存在(n * p / 100)個點在一條直線上

思路

暴力顯然是不可取的,翻閱了題解學習該題,也是第一次接觸這樣的隨機算法。
如果存在一條線滿足情況,有m個點在這條直線上,選取任意兩個點,選中的一個點的在直線上的概率是mn\frac{m}{n},選另一個點的恰好也在直線上的概率就是(m1)n\frac{(m-1)}{n},就變成選中這條直線的概率是m(m1)nn\frac{m*(m-1)}{n * n},選不中這條直線的概率變成了t=(1m(m1)nn)t = (1-\frac{m*(m-1)}{n*n}),然後應該隨機選1000次,全部選不中的概率就是t1000, t<1t <1,1000次方以後接近於0,就隨機枚舉1000次了,沒有隨機取到就impossible

代碼

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e5 + 10;
struct node {
	LL x, y;
}a[N];
int n, p;

void solve() {
	for(int i = 1; i <= n; i++) {
		scanf("%lld%lld", &a[i].x, &a[i].y);
	}

	if(n <= 2) {
		puts("possible");
		return;
	}

	int t = 1000;
	int num = ceil(n * p * 1.0 / 100);
	srand(time(0));
	while(t--) {
		int p1 = (LL)rand() * rand() % n + 1;
		int p2 = (LL)rand() * rand() % n + 1;
		while(p1 == p2) p2 = rand() % n + 1;

		LL x1 = a[p2].x - a[p1].x, y1 = a[p2].y - a[p1].y;
		int cnt = 0;
		for(int i = 1; i <= n; i++) {
			LL x2 = a[i].x - a[p1].x, y2 = a[i].y - a[p1].y;
			if(x1 * y2 == x2 * y1) cnt++;
		}
		if(cnt * 100 >= n * p) {
			puts("possible");
			return;
		}
	}
	puts("impossible");

}

int main() {
	//freopen("in.txt", "r", stdin);
	while(~scanf("%d%d", &n, &p))
		solve();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章