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

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

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

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

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

#include<bits/stdc++.h>
using namespace std;
const int maxn = ;
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<=) return n;
int ans = -;
for(int pivot = ; pivot < n; pivot++){
int k = ;
for(int i = ; 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 = , R = , sum = ;
while(L<k){
if(L == R) { R = (R+)%k; sum++; }
while(R != L && cmp(tmp[L],tmp[R])) {
R = (R+)%k; sum++;
}
ans = max(ans,sum);
sum--; L++;
}
}
return ans;
} int main()
{
int n;
while(~scanf("%d",&n)&&n){
for(int i = ; i < n; i++)
scanf("%d%d%d",&P[i].x,&P[i].y,col+i);
printf("%d\n",solve(n));
}
return ;
}

极角排序

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

#include<bits/stdc++.h>
using namespace std;
const int maxn = ;
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<=) return n;
int ans = -;
for(int pivot = ; pivot < n; pivot++){
int k = ;
for(int i = ; 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 < || (tmp[k].y == && tmp[k].x < ) ) {
tmp[k].x = - tmp[k].x; tmp[k].y = -tmp[k].y;
tmp[k].col = P[i].col^;
}else tmp[k].col = P[i].col;
k++;
}
sort(tmp,tmp+k,cmp);
int w = ,b = ;
int i,j;
for(i = ; i < k; i++) if(tmp[i].col == )w++;
for( i = ; i < k; i = j) {
int lw = ;
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+);
ans = max(ans,k-w-b+j-i+);
w -= lw;
}
}
return ans;
} int main()
{
int n;
while(~scanf("%d",&n)&&n){
for(int i = ; i < n; i++)
scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].col);
printf("%d\n",solve(n));
}
return ;
}

叉积

UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)的更多相关文章

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

    Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new class of ...

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

    Shanghai Hypercomputers, the world's largest computer chip manufacturer, has invented a new classof ...

  3. UVA - 1606 Amphiphilic Carbon Molecules 极角扫描法

    题目:点击查看题目 思路:这道题的解决思路是极角扫描法.极角扫描法的思想主要是先选择一个点作为基准点,然后求出各点对于该点的相对坐标,同时求出该坐标系下的极角,按照极角对点进行排序.然后选取点与基准点 ...

  4. UVA - 1606 Amphiphilic Carbon Molecules (计算几何,扫描法)

    平面上给你一些具有黑或白颜色的点,让你设置一个隔板,使得隔板一侧的黑点加上另一侧的白点数最多.隔板上的点可视作任意一侧. 易知一定存在一个隔板穿过两个点且最优,因此可以先固定以一个点为原点,将其他点中 ...

  5. UVA - 1606 Amphiphilic Carbon Molecules(两亲性分子)(扫描法)

    题意:平面上有n(n <= 1000)个点,每个点为白点或者黑点.现在需放置一条隔板,使得隔板一侧的白点数加上另一侧的黑点数总数最大.隔板上的点可以看做是在任意一侧. 分析:枚举每个基准点i,将 ...

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

    题意:平面上有 n 个点,每个点不是黑的就是白的,现在要放一个隔板,把它们分成两部分,使得一侧的白点数加上另一侧的黑点数最多. 析:这个题很容易想到的就是暴力,不妨假设隔板至少经过两个点,即使不经过也 ...

  7. UVa 1606 - Amphiphilic Carbon Molecules

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  8. 【UVa】1606 Amphiphilic Carbon Molecules(计算几何)

    题目 题目 分析 跟着lrj学的,理解了,然而不是很熟,还是发上来供以后复习 代码 #include <bits/stdc++.h> using namespace std; ; stru ...

  9. poj2280--Amphiphilic Carbon Molecules(扫描线+极角排序+转换坐标)

    题目链接:id=2280">点击打开链接 题目大意:给出n个点的坐标.每一个点有一个值0或者1,如今有一个隔板(无限长)去分开着n个点,一側统计0的个数,一側统计1的个数,假设点在板上 ...

随机推荐

  1. vc++图像显示

    显示资源中的图片 (1)从资源中装入位图 ● 定义位图对象数据成员CBitmap m_Bitmap; ● 调用CBitmap成员函数LoadBitmap(),如m_Bitmap.LoadBitmap( ...

  2. CMD运行指令

    CMD运行指令   开始→运行→CMD→键入以下命令即可:   gpedit.msc-----组策略 sndrec32-------录音机   Nslookup-------IP地址侦测器 explo ...

  3. shell初级-----构建基本脚本

    使用多个命令 如果想要多个命令同时运行,可以把它们放在一行,用分号隔开. date;who 创建shell脚本文件 创建shell脚本时,必须在文件第一行指定要使用的shell #!/bin/bash ...

  4. IDEA Maven Mybatis generator 自动生成代码(实例讲解)(转)

    IDEA Maven Mybatis generator 自动生成代码(实例讲解) MyBatis Generator • 简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的 ...

  5. Unity surface shader 2

    UV滚动 Shader "Nafio/ScrollUV" { Properties { _Tex("T",2D) = "white" {} ...

  6. 自动化测试工具 Test Studio入门教程

    Test Studio安装 可以到下载试用版 官网 http://www.telerik.com/teststudio , 装完以后需要装silverlight 安装好了,主界面是介个样子的 Test ...

  7. LibreOJ #2036. 「SHOI2015」自动刷题机

    #2036. 「SHOI2015」自动刷题机 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 曾经发明了信号增幅仪的发明家 SHTSC 又公开 ...

  8. 洛谷P3757 [CQOI2017]老C的键盘

    传送门 首先可以直接把整个序列建成一个完全二叉树的结构,这个应该都看得出来 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小 ...

  9. Fiddler设置断点修改Request和Response【转】

    Fiddler设置断点修改Request和Response 设置断点的两种方式:工具栏和命令 1.工具栏:Rules -> Automatic Breakpoints(automatic [ɔː ...

  10. 剑指Offer的学习笔记(C#篇)-- 二叉搜索树的后序遍历序列

    题目描述 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 一 . 解题思想与二叉搜索树概念 (1). 二叉树 ...