UVa 1606 两亲性分子 扫描法 && cnt++的分析

博客介绍了如何解决UVa 1606问题,即在平面上放置一条隔板使白点和黑点总数最大化。通过选取基准点,计算相对坐标和极角,动态调整隔板位置。文章提到了一个优化技巧,当点为黑点时,将其旋转180°,简化计算。同时,解析了代码中关于`cnt++`的疑难点,分析了仅在循环开始时需要`cnt++`的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目传送门

题意

平面上有n个点,每个点为白点或者黑点。现在需放置一条隔板,使得隔板一侧的白点数加上另一侧的黑点数总数最大。隔板上的点可以看做是在任意一侧。

思路

每次可以选取两个点作为隔板,所以我们可以先枚举一个基准点,然后算出其他点关于基准点的相对坐标和关于坐标系的极角(可以用atan2函数来计算,返回与x坐标值的角度),剩下的点依次与基准点形成分隔线,然后将一条直线绕基准点旋转,每当直线扫过一个点,就可以动态修改两侧的点数。
本题还有一个优化的方法,那就是如果该点是黑点,就可以将它的坐标关于基准点旋转180°,这样扫描时就只需要计算一侧的白点数了

代码分析(最后会贴lrj完整代码)

开始看lrj的书的时候发现有一个地方没看懂,如下:

    int    L = 0, R = 0, cnt = 2;   //初始点数设为2,即分隔线上的两个点
    while (L < k)   //每个点都尝试与基点成为分割线
    {
        if (R == L)  { R = (R + 1) % k; cnt++; }  //空区域  **疑惑的地方**
        while (R != L && left(p[L], p[R]))   //R不等于L并且在180度之内
        {
            R = (R + 1) % k;
            cnt++;
        }
        cnt--; //分隔线旋转,原本在分隔线上的点到了右边,所以要减去
        L++;  //分隔线旋转
        ans = max(ans, cnt);
    }

然后翻阅了一下博客,发现比较详细的博客中有详细的代码注释,但是没看到分析的地方,所以我自己思考后想

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值