圆的扫描线

有关圆的扫描线的学习就告一段落了,这里总结下。
圆的扫描线是有条件的:任意圆之间,只有包含跟相离这两种条件。
怎么扫描呢?
假如是从左往右扫,set从上到下保存圆,假设碰到一个圆,那么碰到的一定是这个圆的左端点,我们把它丢到set里,当再也扫不到它的时候,很显然就是碰到它的右端点的时候,这个时候把它从set中丢掉。
然后具体讨论要做什么操作的时候,就可以自己构造了,就用下面这三个例题来说明吧。


poj2932
题意:很多很多圆,输出没有被其它圆包含的圆的编号。
做法:set中只保留没被其它圆包含的圆,所以判断某个圆是否被包含的时候,只需要找出已经扫过的圆中,跟它最近的上下两个圆,然后判断是否包含它即可。


HDU3511
题意:很多很多圆,输出被包含最多次的圆被包含的次数。

做法:借用这个链接http://www.cppblog.com/superlong/archive/2010/08/06/122427.html

需要注意的是,如果从左往右扫,这里的set应该按照在扫面线上的点的y从上往下或者从下往上排序。因为这个题不仅仅是求边界圆,所以要这样处理,而不能按照上题不考虑扫面线,直接按照y排序。


HDU5299

题意:很多很多圆,你每次可以删除一个圆以及被他包含的所有圆,现在有两个人轮流选择删除,问博弈的话,谁会赢?

做法:博弈的话就是“树上的删边游戏”。如何建树?只需要找出每个圆的父亲节点连边即可,当然可能会形成很多森林,再弄一个点做跟连接所有森林的根形成一棵树即可。至于如何找圆与圆的关系,链接里分析的很清楚了,可直接套用结论,对HDU3511稍作变化即可。

下面是链接里的原文以及我的AC代码:

用一条竖直线从左到右扫描所有的圆,处理每个圆“刚接触扫描线”和“刚离开
扫描线”两个事件点。
为了下面描述方便,令某圆A的嵌套层数为f(A), 如果某圆A被某圆B嵌套且A和B
紧邻,那么说A是B的儿子,B是A的父亲。如果圆A,圆B同时是圆C的儿子,那么A,
B互为兄弟,当前考虑的圆为圆C。

根据“刚接触扫描线”事件点的上下相邻事件点分类有如下情况:
1)没有上方事件点,或者没有下方事件点。这时该圆C的嵌套层数f(C) = 1
2)上方事件点和下方事件点属于同一个圆A,这时圆A必定是圆C的父亲,f(C) =
f(A) + 1
3)上方事件点和下方事件点分别属于两个圆A,B,且f(A) != f(B),这里不妨
设f(A) < f(B),那么A是C的父亲,B是C的兄弟。f(C) = f(A) + 1, f(C) = f(B)
4) 上方事件点和下方事件点分别属于两个圆A,B,且f(A) == f(B),那么A是C
的兄弟,B是C的兄弟,f(C) = f(A) = f(B).
在处理“刚接触扫描线”事件点时插入一对点表示该圆与扫描线的相交情况,
并利用上述分类计算其嵌套层数,在处理“ 刚离开扫描线”事件点是删除对应
的那一对点。可以采用STL 中的set来维护

poj2932

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef pair<double,int>ll;
vector<ll>bx;
set<ll>st;
set<ll>::iterator it;
double r[40010],x[40010],y[40010];
bool isok(int id,int jd)
{
	return pow(x[id]-x[jd],2)+pow(y[id]-y[jd],2)<=pow(r[id],2);
}
vector<int>ans;
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%lf%lf%lf",r+i,x+i,y+i);
		bx.push_back(ll(x[i]-r[i],i));
		bx.push_back(ll(x[i]+r[i],i+n));
	}
	sort(bx.begin(),bx.end());
	int m=2*n;
	for(int i=0;i<m;i++)
	{
		int id=bx[i].second%n;
		if(bx[i].second<n)
		{
			it=st.lower_bound(ll(y[id],id));
			if(it!=st.end()&&isok(it->second,id))
				continue;
			if(it!=st.begin()&&isok((--it)->second,id))
				continue;
			st.insert(ll(y[id],id));
			ans.push_back(id);
		}
		else
			st.erase(ll(y[id],id));
	}
	sort(ans.begin(),ans.end());
	m=ans.size();
	printf("%d\n",m);
	for(int i=0;i<m;i++)
	{
		if(i)
			putchar(' ');
		printf("%d",ans[i]+1);
	}
	return 0;
}

hdu3511

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef pair<double,int>ll;
double x[50010],y[50010],r[50010];
vector<ll>bx;
double linenow;
struct node
{
    int id;
    bool up;
    node(){}
    node(int id,bool up)
    {
        this->id=id;
        this->up=up;
    }
    double gety()const
    {
        return y[id]+sqrt(pow(r[id],2)-pow(x[id]-linenow,2))*(up?1:-1);
    }
    bool operator <(const node a)const
    {
        double ay=gety(),by=a.gety();
        return ay!=by?ay>by:up>a.up;
    }
};
set<node>st;
set<node>::iterator it,jt;
int cnt[50010];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        bx.clear();
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf",x+i,y+i,r+i);
            bx.push_back(ll(x[i]-r[i],i));
            bx.push_back(ll(x[i]+r[i],i+n));
        }
        sort(bx.begin(),bx.end());
        int m=n*2,ans=0;
        for(int i=0;i<m;i++)
        {
            int id=bx[i].second%n;
            if(bx[i].second>=n)
            {
                st.erase(node(id,0));
                st.erase(node(id,1));
                continue;
            }
            linenow=bx[i].first;
            it=jt=st.insert(node(id,1)).first;
            if(it==st.begin()||++jt==st.end())
                cnt[id]=1;
            else
            {
                it--;
                if(it->id==jt->id)
                    cnt[id]=cnt[it->id]+1;
                else
                    cnt[id]=max(cnt[it->id],cnt[jt->id]);
            }
            ans=max(ans,cnt[id]);
            st.insert(node(id,0));
        }
        printf("%d\n",ans);
    }
}

hdu5299

#include<map>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<climits>
#include<list>
#include<iomanip>
#include<stack>
#include<set>
using namespace std;
typedef pair<double,int>ll;
struct Edge
{
    int to,next;
}edge[20010];
int head[20010],tail;
void add(int from,int to)
{
    edge[tail].to=to;
    edge[tail].next=head[from];
    head[from]=tail++;
}
int dfs(int from)
{
    int ans=0;
    for(int i=head[from];i!=-1;i=edge[i].next)
        ans^=dfs(edge[i].to)+1;
    return ans;
}
double x[50010],y[50010],r[50010];
vector<ll>bx;
double linenow;
struct node
{
    int id;
    bool up;
    node(){}
    node(int id,bool up)
    {
        this->id=id;
        this->up=up;
    }
    double gety()const
    {
        return y[id]+sqrt(pow(r[id],2)-pow(x[id]-linenow,2))*(up?1:-1);
    }
    bool operator <(const node a)const
    {
        double ay=gety(),by=a.gety();
        return ay!=by?ay>by:up>a.up;
    }
};
set<node>st;
set<node>::iterator it,jt;
int cnt[50010],fa[50010];
void create(int n)
{
	tail=0;
    memset(head,-1,sizeof(head));
	sort(bx.begin(),bx.end());
    int m=n*2,ans=0;
    for(int i=0;i<m;i++)
    {
        int id=bx[i].second%n;
        if(bx[i].second>=n)
        {
            st.erase(node(id,0));
            st.erase(node(id,1));
            continue;
        }
        linenow=bx[i].first;
        it=jt=st.insert(node(id,1)).first;
        if(it==st.begin()||++jt==st.end())
        {
        	cnt[id]=1;
        	fa[id]=n;
        	add(n,id);
        }
        else
        {
            it--;
            if(it->id==jt->id)
            {
            	cnt[id]=cnt[it->id]+1;
            	fa[id]=it->id;
            	add(it->id,id);
            }
            else
            {
            	cnt[id]=max(cnt[it->id],cnt[jt->id]);
            	if(cnt[it->id]<cnt[jt->id])
            	{
            		fa[id]=it->id;
            		add(it->id,id);
            	}
            	else if(cnt[it->id]>cnt[jt->id])
            	{
            		fa[id]=jt->id;
            		add(jt->id,id);
            	}
            	else
            	{
            		fa[id]=fa[it->id];
            		add(fa[it->id],id);
            	}
			}
        }
        st.insert(node(id,0));
    }
}
int main()
{
	int T;
	scanf("%d",&T);
    while(T--)
    {
    	int n;
    	scanf("%d",&n);
        bx.clear();
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf",x+i,y+i,r+i);
            bx.push_back(ll(x[i]-r[i],i));
            bx.push_back(ll(x[i]+r[i],i+n));
        }
        create(n);
        puts(dfs(n)!=0?"Alice":"Bob");
    }
}


Coneology
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 3307 Accepted: 591

Description

A student named Round Square loved to play with cones. He would arrange cones with different base radii arbitrarily on the floor and would admire the intrinsic beauty of the arrangement. The student even began theorizing about how some cones dominate other cones: a cone A dominates another cone B when cone B is completely within the cone A. Furthermore, he noted that there are some cones that not only dominate others, but are themselves dominated, thus creating complex domination relations. After studying the intricate relations of the cones in more depth, the student reached an important conclusion: there exist some cones, all-powerful cones, that have unique properties: an all-powerful cone is not dominated by any other cone. The student became so impressed by the mightiness of the all-powerful cones that he decided to worship these all-powerful cones.

Unfortunately, after having arranged a huge number of cones and having worked hard on developing this grandiose cone theory, the student become quite confused with all these cones, and he now fears that he might worship the wrong cones (what if there is an evil cone that tries to trick the student into worshiping it?). You need to help this student by finding the cones he should worship.

Input

The input le specifies an arrangement of the cones. There are in total N cones (1 ≤ N ≤ 40000). Cone i has radius and height equal to Rii = 1 … N. Each cone is hollow on the inside and has no base, so it can be placed over another cone with smaller radius. No two cones touch.

The first line of the input contains the integer N. The next N lines each contain three real numbers Rixiyi separated by spaces, where (xiyi) are the coordinates of the center of the base of cone i.

Output

The first line of the output le should contain the number of cones that the student should worship. The second line contains the indices of the cones that the student should worship in increasing order. Two consecutive numbers should be separated by a single space.

Sample Input

5
1 0 -2
3 0 3
10 0 0
1 0 1.5
10 50 50

Sample Output

2
3 5

Source


Prison Break

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1919    Accepted Submission(s): 576


Problem Description
To save Sara, Michael Scofield was captured by evil policemen and he was arrested in Prison again. As is known to all, nothing can stop Michael, so Prison Break continues.
The prison consists of many circular walls. These walls won't intersect or tangent to each other. 



Now Michael is arrested in one of the deepest rooms, and he wants to know how many walls he has to break at least for running out. In figure 1, Michael has to break 3 walls at least and in figure 2, 2 walls are needed.
 

Input
There will be multiple test cases (no more than 10) in a test data.
For each test case, the first line contains one number: n (1<=n<=50,000) indicating the total number of circular walls.
Then n lines follow, each line contains three integers x, y, r. (x,y) indicates the center of circular wall and r indicates the radius of the wall.
-100,000<=x,y<=100,000 
1 <= r <= 100,000
The input ends up with EOF.
 

Output
The least number of walls to break for running out.
 

Sample Input
   
   
3 0 0 1 0 0 2 0 0 3 3 0 0 10 5 0 1 -5 0 1
 

Sample Output
   
   
3 2
 

Source
 

Recommend
zhouzeyong

Circles Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1268    Accepted Submission(s): 397


Problem Description
There are n circles on a infinitely large table.With every two circle, either one contains another or isolates from the other.They are never crossed nor tangent.
Alice and Bob are playing a game concerning these circles.They take turn to play,Alice goes first:
1、Pick out a certain circle A,then delete A and every circle that is inside of A.
2、Failling to find a deletable circle within one round will lost the game.
Now,Alice and Bob are both smart guys,who will win the game,output the winner's name.
 

Input
The first line include a positive integer T<=20,indicating the total group number of the statistic.
As for the following T groups of statistic,the first line of every group must include a positive integer n to define the number of the circles.
And the following lines,each line consists of 3 integers x,y and r,stating the coordinate of the circle center and radius of the circle respectively.
n≤20000,|x|≤20000,|y|≤20000,r≤20000。
 

Output
If Alice won,output “Alice”,else output “Bob”
 

Sample Input
   
   
2 1 0 0 1 6 -100 0 90 -50 0 1 -20 0 1 100 0 90 47 0 1 23 0 1
 

Sample Output
   
   
Alice Bob
 

Author
FZUACM
 

Source


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值