HOJ 13348 Finding Lines 画直线最多点

传送门:http://acm.hnu.cn/online/?action=problem&type=show&id=13348&courseid=320

Finding Lines

Time Limit: 20000ms, Special Time Limit:50000ms, Memory Limit:65536KB
Total submit users: 25, Accepted users: 11
Problem 13348 : No special judgement
Problem description

Annabel and Richard like to invent new games and play against each other. One day Annabel has a new game for Richard. In this game there is a game master and a player. The game master draws n points on a piece of paper. The task for the player is to find a straight line, such that at least p percent of the points lie exactly on that line. Richard and Annabel have very good tools for measurement and drawing. Therefore they can check whether a point lies exactly on a line or not. If the player can find such a line then the player wins. Otherwise the game master wins the game.

There is just one problem. The game master can draw the points in a way such that it is not possible at all to draw a suitable line. They need an independent mechanism to check whether there even exists a line containing at least p percent of the points, i.e., dn · p/100e points. Now it is up to you to help them and write a program to solve this task.


Input

The input consists of:

• one line with one integer n (1 ≤ n ≤ 10^5), the number of points the game master has drawn;

• one line with one integer p (20 ≤ p ≤ 100), the percentage of points which need to lie on the line;

• n lines each with two integers x and y (0 ≤ x,y ≤ 10^9), the coordinates of a point. No two points will coincide.


Output

Output one line containing either “possible” if it is possible to find a suitable line or “impossible” otherwise.


Sample Input
5
55
0 0
10 10
10 0
0 10
3 3
5
45
0 0
10 10
10 0
0 10
3 4
Sample Output
possible
impossible
Judge Tips


Problem Source
NWERC 2014

/******************************************************************
*   给n(10w)点,画一条直线至少有ceil(n*p/100.)个点(20<=p<=100)
*   ceil取上整,做法 从n个点钟随机选取两个点枚举其余点
*   手写随机比系统随机更有效,亲测!!!
******************************************************************/
#include
#include
#include
using namespace std;
#define LL long long
int x[100001],y[100001];
int n,p;
unsigned int suiji(){
    //手写随机,42和22695477可以随机改,亲测39和246813579更快
    static unsigned int seed=42;
    return seed = 22695477*seed+1;
}
inline int online(int x1,int y1,int x2,int y2){
    if((LL)(x1)*(LL)(y2)-(LL)(x2)*(LL)(y1)==0 )return 0;
    return 1;
}
int main(){
    while(~scanf("%d%d",&n,&p)){
        for(int i=0;i=n*p){
                    flag=true;
                    break;
                }
            }
            if(flag)break;
        }
        if(flag)puts("possible");
        else puts("impossible");
    }
    return 0;
}

/************************************************************
*   随机姿势:随机1w次选取两点map保存斜率并统计
*   斜率次数>230 去暴力n个点
*************************************************************/
#include
#include
#include
#include
using namespace std;
#define LL long long
LL x[100001],y[100001];
LL n,p;
LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
struct Line{
    LL a,b,c;
    Line(LL x1=0,LL y1=0,LL x2=0, LL y2=0){
        LL d = gcd(abs(x1-x2), abs(y1-y2));
        if (x1 mapt;
int main(){
    while(~scanf("%64d%I64d",&n,&p)){
        for(LL i=0;i::iterator it;
        LL a,b,c;
        bool flag=false;
        for(it=mapt.begin();it!=mapt.end();it++){
            if(it->second > 230){
                cnt=0;
                a=it->first.a;
                b=it->first.b;
                c=it->first.c;
                for(LL i=0;i=p*n){
                        flag=true;
                        break;
                    }
                }
                if(flag)break;
            }
        }
        if(flag)puts("possible");else puts("impossible");
    }
    return 0;
}

#include
#include
#include
#include
using namespace std;
#define LL long long
int x[100001],y[100001];
int gcd(int a,int b){return b==0?a:gcd(b,a%b); }
struct Line{
    LL a,b,c;
    Line(int x1=0,int y1=0,int x2=0,int y2=0){
        int d=gcd(abs(x1-x2),abs(y1-y2));
        if(x1 findline(int l,int r,int p){
    int m=(l+r)>>1;
    setS,S1;
    if(100>=p*(m-l+1)){//too little point
        for(int i=l;i<=r;i++)
            for(int j=i+1;j<=r;j++)
                S1.insert(Line(x[i],y[i],x[j],y[j]));
    }else{
        S1 = findline(l,m,p);
        set S2=findline(m+1,r,p);
        S1.insert(S2.begin(),S2.end());
    }
    set::iterator it;
    LL a,b,c;
    int cnt;
    for(it=S1.begin();it!=S1.end();it++){
        a=it->a;
        b=it->b;
        c=it->c;
        cnt=0;
        for(int i=l;i<=r;i++)
            if(a*x[i] + b*y[i] == c)
                cnt++;
        if(cnt*100 >= p*(r-l+1))
            S.insert(*it);
    }
    return S;
}
int main(){
    int n,p;
    while(~scanf("%d%d",&n,&p)){
        for(int i=0;i





你可能感兴趣的:(计算几何)