• UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)


    任意线可以贪心移动到两点上。直接枚举O(n^3),会TLE。

    所以采取扫描法,选基准点,然后根据极角或者两两做叉积比较进行排排序,然后扫一遍就好了。旋转的时候在O(1)时间推出下一种情况,总复杂度为O(n^2logN)就可以过了。

    另外,本题有个很巧妙的技巧,就是一点等效与相反坐标的相反颜色的点。

    第一次写,细节还是蛮多的,花了好久才搞清所有细节。。。

    极角排序版,比较容易理解,932ms。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1003;
    struct Point
    {
        int x,y;
        double rad;
        bool operator<(const Point &rhs) const {
            return rad < rhs.rad;
        }
    }P[maxn];
    int col[maxn];
    
    Point tmp[maxn];
    
    
    bool cmp(const Point& a,const Point& b) //anticlockwise sort
    {
        return a.x*b.y >= b.x*a.y;
    }
    
    int solve(int n)
    {
        if(n<=3) return n;
        int ans = -1;
        for(int pivot = 0; pivot < n; pivot++){
            int k = 0;
            for(int i = 0; i < n; i++) if(i!=pivot){
                tmp[k].x = P[i].x - P[pivot].x;
                tmp[k].y = P[i].y - P[pivot].y;
                if(col[i]) { tmp[k].x = - tmp[k].x; tmp[k].y = -tmp[k].y; }
                tmp[k].rad = atan2(tmp[k].y, tmp[k].x);
                k++;
            }
            sort(tmp,tmp+k);
            int L = 0, R = 0, sum = 1;
            while(L<k){
                if(L == R) { R = (R+1)%k; sum++; }
                while(R != L && cmp(tmp[L],tmp[R])) {
                    R = (R+1)%k; sum++;
                }
                ans = max(ans,sum);
                sum--;  L++;
            }
        }
        return ans;
    }
    
    int main()
    {
        int n;
        while(~scanf("%d",&n)&&n){
            for(int i = 0; i < n; i++)
                scanf("%d%d%d",&P[i].x,&P[i].y,col+i);
                printf("%d
    ",solve(n));
        }
        return 0;
    }
    极角排序

    如果卡精度,那么就用叉积两两比较,算极角常数大一些,叉积跑的快一点577ms。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1003;
    struct Point
    {
        int x,y,col;
    }P[maxn],tmp[maxn];;
    
    
    
    inline int cross(const Point& a,const Point& b)
    {
        return a.x*b.y - b.x*a.y;
    }
    
    
    
    bool cmp(const Point& a,const Point& b) //anticlockwise sort
    {
        return a.x*b.y > b.x*a.y;
    }
    
    int solve(int n)
    {
        if(n<=3) return n;
        int ans = -1;
        for(int pivot = 0; pivot < n; pivot++){
            int k = 0;
            for(int i = 0; i < n; i++) if(i!=pivot){
                tmp[k].x = P[i].x - P[pivot].x;
                tmp[k].y = P[i].y - P[pivot].y;
                if(tmp[k].y < 0 || (tmp[k].y == 0 && tmp[k].x < 0) ) {
                    tmp[k].x = - tmp[k].x; tmp[k].y = -tmp[k].y;
                    tmp[k].col = P[i].col^1;
                }else tmp[k].col = P[i].col;
                k++;
            }
            sort(tmp,tmp+k,cmp);
            int w = 0,b = 0;
            int i,j;
            for(i = 0; i < k; i++) if(tmp[i].col == 0)w++;
            for( i = 0; i < k; i = j) {
                int lw = 0;
                for(j = i; j < k; j++) {
                    if(cross(tmp[i],tmp[j])) break;
                    if(tmp[j].col) b++;
                    else lw++;
                }
                ans = max(ans,w+b+1);
                ans = max(ans,k-w-b+j-i+1);
                w -= lw;
            }
        }
        return ans;
    }
    
    int main()
    {
        int n;
        while(~scanf("%d",&n)&&n){
            for(int i = 0; i < n; i++)
                scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].col);
            printf("%d
    ",solve(n));
        }
        return 0;
    }
    叉积

     

  • 相关阅读:
    建站两个月,说说我的想法
    我见过的郭弃疾先生(兰亭集势CEO)
    C#数组和集合互相转换的几种方法的效率分析
    (五)React Ant Design Pro + .Net5 WebApi:后端环境搭建Autofac注入+ 泛型仓储
    关于C++中对私有的测试总结
    uint8_t / uint16_t / uint32_t /uint64_t 是什么数据类型(转)
    GDB调试
    linux删除乱码文件
    转:C++ nan
    vim
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4693461.html
Copyright © 2020-2023  润新知