POJ 2280 && HDU 1661 Amphiphilic Carbon Molecules

题目大意:

在平面上有一些点,每个点都有0,1其中一个属性。要求用一条直线将平面分成两部分。其中一部分取属性为0的点,另一部分取属性为1的点。若点在直线上全部取走,问最多能取多少个点。

解题思路:

扫描线算法。枚举任意一点,其他点依照那一点进行极角排序。扫描获得最大值。

注意:

1、因为 atan2方式的极角排序有精度误差,在这里需要用叉积方式排序。否则就自己慢慢测精度去吧!

2、用叉积方式的极角排序需要将排序的点提前处理到两个象限范围内。注意点属性的状态转换。

3、POJ数据较弱,HDU数据较强。两个OJ都是C++较慢。

下面是代码:

#include <set>
#include <map>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>

#define eps 1e-8
#define pi acos(-1.0)
#define inf 107374182
#define inf64 1152921504606846976
#define lc l,m,tr<<1
#define rc m + 1,r,tr<<1|1
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define clear1(A, X, SIZE) memset(A, X, sizeof(A[0]) * (SIZE))
#define clearall(A, X) memset(A, X, sizeof(A))
#define memcopy1(A , X, SIZE) memcpy(A , X ,sizeof(X[0])*(SIZE))
#define memcopyall(A, X) memcpy(A , X ,sizeof(X))
#define max( x, y )  ( ((x) > (y)) ? (x) : (y) )
#define min( x, y )  ( ((x) < (y)) ? (x) : (y) )

using namespace std;

int n,pointnum,ans,cnt,l,r,sum,num,p;

struct node1
{
    int x,y,sta;
} Point[1005],temp[1005];

int detmul(const node1 a,const node1 b)
{
    return a.x * b.y - b.x * a.y;
}

bool cmp(const node1 a,const node1 b)
{
    return detmul(a,b)>0;
}

int main()
{
    while(scanf("%d",&n),n)
    {
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d",&Point[i].x,&Point[i].y,&Point[i].sta);
        }
        ans=0;
        for(pointnum=0; pointnum<n; pointnum++)
        {
            cnt=0;
            for(int i=0; i<n; i++)
            {
                if(i==pointnum)continue;
                temp[cnt].x=Point[i].x-Point[pointnum].x;
                temp[cnt].y=Point[i].y-Point[pointnum].y;
                temp[cnt].sta=Point[i].sta;
                if(temp[cnt].y<0||(temp[cnt].y==0&&temp[cnt].x<0))
                {
                    temp[cnt].x*=-1;
                    temp[cnt].y*=-1;
                    temp[cnt].sta=!temp[cnt].sta;
                }
                cnt++;
            }
            sort(temp,temp+cnt,cmp);
            l=0;
            r=0;
            sum=0;
            for(int i=0;i<cnt;i++)
            {
                if(temp[i].sta==0)l++;
            }
            for(int i=0;i<cnt;i=p)
            {
                num=0;
                for(p=i;p<cnt;p++)
                {
                    if(detmul(temp[i],temp[p]))break;
                    if(temp[p].sta)r++;
                    else num++;
                }
                sum=max(sum,l+r+1);
                sum=max(sum,cnt-l-r+p-i+1);
                l-=num;
            }
            ans=max(ans,sum);
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-09 19:28:03

POJ 2280 && HDU 1661 Amphiphilic Carbon Molecules的相关文章

POJ 2280&amp;&amp;hdu 1661

题意:给定平面上的N个点,属性分别标记为0和1,然后找一条直线,直线上的点全部溶解,一侧的1溶解,另一侧的0溶解.求出最多能溶解的点的个数. 思路:暴力枚举每个点,扫描线旋转.先做优化,如果一侧溶解0,则把属性为1的做关于当前枚举直线对称的点,这样统计一侧的点加上线上的点就是答案.O(n2). 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5

Amphiphilic Carbon Molecules

Description: Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new class of nanoparticles called Amphiphilic Carbon Molecules (ACMs). ACMs are semiconductors. It means that they can be either conductors or insula

uva 1606 amphiphilic carbon molecules【把缩写写出来,有惊喜】(滑动窗口)——yhx

Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new classof nanoparticles called Amphiphilic Carbon Molecules (ACMs). ACMs are semiconductors. It meansthat they can be either conductors or insulators of electro

【极角排序、扫描线】UVa 1606 - Amphiphilic Carbon Molecules(两亲性分子)

Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new class of nanoparticles called Amphiphilic Carbon Molecules (ACMs). ACMs are semiconductors. It means that they can be either conductors or insulators of elect

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

任意线可以贪心移动到两点上.直接枚举O(n^3),会TLE. 所以采取扫描法,选基准点,然后根据极角或者两两做叉积比较进行排排序,然后扫一遍就好了.旋转的时候在O(1)时间推出下一种情况,总复杂度为O(n^2logN)就可以过了. 另外,本题有个很巧妙的技巧,就是一点等效与相反坐标的相反颜色的点. 第一次写,细节还是蛮多的,花了好久才搞清所有细节... 极角排序版,比较容易理解,932ms. #include<bits/stdc++.h> using namespace std; const

UVa1606 Amphiphilic Carbon Molecules (扫描法+极角排序)

链接:http://vjudge.net/problem/UVA-1606 分析:不妨先假设隔板一定经过至少两个点(否则可以移动隔板使其经过经过两个点,由于在隔板上的点可以看作是在任意一侧,所以总数并不会变小).最简单的想法是,枚举两个点,然后输出两侧黑白点的个数,枚举量是O(n²),再加上统计的O(n),总时间复杂度是O(n³),太大. 可以先枚举一个基准点,然后将一条直线绕这个基准点旋转.其它点要按照相对基准点的极角排序,这里有一个技巧就是把所有黑点或者白点的坐标作一个中心对称,这样以后就只

UVa1606 UVaLive3259 FZU1309 HDU1661 POJ2280 ZOJ2390 Amphiphilic Carbon Molecules

填坑系列 考虑所有经过两个点的直线,一定有最优解. 再考虑确定一个点,按极角顺序枚举所有直线,从而O(1)转移信息. 还有代码实现技巧 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 7 const int N = 1000 + 10; 8 9 typedef const struct P

UVa 1606 (极角排序) Amphiphilic Carbon Molecules

如果,没有紫书上的翻译的话,我觉得我可能读不懂这道题.=_=|| 题意: 平面上有n个点,不是白点就是黑点.现在要放一条直线,使得直线一侧的白点与另一侧的黑点加起来数目最多.直线上的点可以看作位于直线的任意一侧. 分析: 首先假设直线经过两个点,否则可以移动直线使其经过两个点,并且总数不会减少. 所以,我们可以先枚举一个基点,然后以这个点为中心. 围绕基点将其他点按照极角排序,将直线旋转,统计符合要求的点的个数. 小技巧: 如果将所有的黑点以基点为中心做一个中心对称,则符合要求的点的个数就变成了

UVa 1606 Amphiphilic Carbon Molecules (扫描法+极角排序)

题意:平面上有 n 个点,每个点不是黑的就是白的,现在要放一个隔板,把它们分成两部分,使得一侧的白点数加上另一侧的黑点数最多. 析:这个题很容易想到的就是暴力,不妨假设隔板至少经过两个点,即使不经过也可以通过平移使它经过,然后每次枚举两个点,当作隔板,枚举量是n*n, 然后计算是 n,那么时间复杂度就是 n3 ,一定会超时的,我产可以这样想,先枚举一个点,然后绕这个点旋转,每扫过一个点,就动态修改两侧的点数, 在转一周过程中,每个点至多扫到两次,这个过程复杂是 n,扫描前进行极角,时间复杂度是