hdu 6976/ 2021“MINIEYE杯”中国大学生算法设计超级联赛(3)1004 Game on Plane

https://acm.hdu.edu.cn/showproblem.php?pid=6976

 

题意:

有n条直线,Alice和Bob玩n次游戏

第i次游戏Alice先选i条直线,Bob再画任意一条直线

Bob的罚分为与画的直线相交的被选中的直线数

Alice想让罚分尽可能大,Bob想让罚分尽可能小

求每次游戏的罚分

 

对于Alice的一种选法,Bob肯定是画一条斜率为出现次数最多的斜率的直线

因为只有平行才不相交

所以Alice要最小化出现次数最多的斜率的最大值

所以就依次从每种斜率选1个,都选了1个之后再选第2个……

 

#include<bits/stdc++.h>

using namespace std;

#define N 100001

double k[N];
int sum[N];

const double eps=1e-11;

int main()
{
    int T,n,x1,y1,x2,y2,m,mi;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(x1!=x2) k[i]=1.0*(y1-y2)/(x1-x2);
            else k[i]=1e10;
        }
        sort(k+1,k+n+1);
        for(int i=1;i<=n;++i) sum[i]=0;
        m=1;
        sum[1]=1;
        for(int i=2;i<=n;++i)
            if(k[i]-k[i-1]<eps) sum[m]++;
            else sum[++m]=1;
        sort(sum+1,sum+m+1);
    //    for(int i=1;i<=tmp;++i) tmp[i]=sum[i];
    //    int mm=unique(tmp+1,tmp+m+1)-tmp-1;
        int now=1,lev=1,last=1;
        for(int i=1;i<=n;++i)
        {
            printf("%d\n",i-lev);
            ++now;
            if(now>m) 
            {
                ++lev;
                now=last;
                while(sum[now]<lev) ++now;
                last=now;
            }    
        }
    }
}

 

posted @ 2021-08-10 17:41  TRTTG  阅读(95)  评论(0编辑  收藏  举报