vijos p1883 月光的魔法

背景

影几欺哄了众生了
天以外——
月儿何曾圆缺

描述

有些东西就如同月光的魔法一般.

Luke是爱着vijos的.
他想为自己心爱的东西画些什么.

就画N个圆吧.
把它们的圆心都固定在x轴上.

圆与圆.
为了爱,两两不能相交.
为了爱,它们可以互相贴在一起.
内切或外切,都是允许的.

vijos的美丽,在于人心.
vijos的孩子们,一定能告诉大家:Luke画的圆究竟把平面分割成了多少块?

月光恬美地洒在大地上.
Luke知道,如果什么都不画,平面就只有一块.多美呢!
Luke知道,只画一个圆,平面就分成了两块.也很美呢!
但Luke还是要多画一些的,因为他真的深爱着vijos呢.

格式

输入格式

输入数据第一行:输出一个整数N,1<=N<=300,000.表示圆的个数.
之后N行,每一行有2个整数,x[i]和r[i]表示圆心固定在x[i]的位置,半径为r[i].
-1,000,000,000<=x[i]<=1,000,000,000
1<=r[i]<=1,000,000,000
所有圆都是唯一的,不会出现重叠.

输出格式

输出只有一行,要求输出平面被分割成了多少块.

样例1

样例输入1

2
1 3
5 1

样例输出1

3

样例2

样例输入2[复制]

3
2 2
1 1
3 1

样例输出2[复制]

5

样例3

样例输入3[复制]

4
7 5
-9 11

样例输出3[复制]

6

    关于这道题,我确实花了不少功夫,这道题的关键在于所有的圆位置关系只有内切、外切、内含、外含四种关系,不存在两个圆相互交叉。所以理论上有n个圆,平面就被分成n+1个,之所以多是因为有些圆被其他几个圆分成了两个了,看懂这一点就成功了一点了。接下来就是代码问题了,我的思路就是先给圆排序,左端点优先,由小到大排。如果左端点相同半径大的在前面。这之后就请看代码吧,相关解释在代码里面,我觉得更清晰点。

记录信息

评测状态Accepted
题目P1883 月光的魔法
递交时间2015-02-27 12:25:33
代码语言C
评测机VijosEx
消耗时间355 ms
消耗内存4948 KiB
评测时间2015-02-27 12:25:35

评测结果

编译成功

foo.c: In function 'result':
foo.c:32:15: warning: variable 'k' set but not used [-Wunused-but-set-variable]
{ int i,j,p,k,q,o;
^

测试数据 #0: Accepted, time = 0 ms, mem = 4944 KiB, score = 10

测试数据 #1: Accepted, time = 0 ms, mem = 4948 KiB, score = 10

测试数据 #2: Accepted, time = 0 ms, mem = 4948 KiB, score = 10

测试数据 #3: Accepted, time = 0 ms, mem = 4948 KiB, score = 10

测试数据 #4: Accepted, time = 15 ms, mem = 4948 KiB, score = 10

测试数据 #5: Accepted, time = 46 ms, mem = 4948 KiB, score = 10

测试数据 #6: Accepted, time = 62 ms, mem = 4948 KiB, score = 10

测试数据 #7: Accepted, time = 46 ms, mem = 4948 KiB, score = 10

测试数据 #8: Accepted, time = 62 ms, mem = 4944 KiB, score = 10

测试数据 #9: Accepted, time = 124 ms, mem = 4944 KiB, score = 10

Accepted, time = 355 ms, mem = 4948 KiB, score = 100

#include "stdio.h"
#include "stdlib.h"
struct yuan   //构造一个结构体来盛放相关信息
{   int xin;   //记录圆心
    int ban;   //记录半径
    int left;  //记录左端点
    int right; //记录右端点
}a[300000];  /*1<=N<=300,000,所以构造一个盛300000元素的数组,在这说明一点,这个数组要在所有函数外面,不要放在主函                            数里,否则会报错,这是因为这个数组占用空间太大,主函数里的数组最多好像只能开到千位,当然这是c(目前我只学了c                           ,c++刚了解),别的语言还不清楚*/
void result(struct yuan a[],int n);
int cmp(const void *a,const void *b)
{   struct yuan *p=(struct yuan *)a;
	struct yuan *q=(struct yuan *)b;
	if(p->left!=q->left)
	   return (p->left)-(q->left);
	else
	   return (q->xin)-(p->xin);
}
int main() 
{   int N,i;
	while(scanf("%d",&N)!=EOF)
	{   for(i=0;i<N;i++)
	   	{   scanf("%d%d",&a[i].xin,&a[i].ban);
	   	    a[i].left=a[i].xin-a[i].ban;
	   	    a[i].right=a[i].xin+a[i].ban;
	   	}
	   	qsort(a,N,sizeof(a[0]),cmp);/*数组排序,如果是c++的话用sort会更方便也更为稳定,原因可以看看两个函数                                               写cmp函数的区别,一目了然*/
	   	result(a,N);//这个用来寻找有几个圆被分成了两个
	}
    return 0;   
}
void result(struct yuan a[],int n)
{   int i,j,p,k,q,o;
	int sum=n+1;  //sum用来记录平面的个数,初始值为n+1,有几个圆被平分就加上几
	for(i=0;i<n-1;i++)
	{   if(a[i].left!=a[i+1].left) //如果一个圆被平分,那么排序后这个圆的下一个圆左端点肯定相同,否则不被平分
		    continue;
            j=i+2;k=1;o=0;
	    if(j>=n)
		 break;
	    while(a[i].right>=a[j].right)//如果一个圆被平分,那么平分它的圆肯定在它里面
	    {    p=j-1;   
	    	 while(a[p].right>=a[j].right)//这是寻找第一个左端点不同且在a[p]圆外的圆
	    	 {    j++;
	    	      if(j>=n)
	    	         break;
	    	 }
	    	 if(a[p].right!=a[j].left)//如果一个圆平分,那么平分它的圆应该是连续的
	    	 {    k=0;
	    	      break;
	    	 }
	    	 q=j;
	    	 if((a[i].right==a[q].right)&&(a[q].left==a[p].right))//判断该圆是否符合被平分
	    	 {     o=1;
	    	       break;
	    	 }   
	    	 j++;
	    	 if(j>=n)
	    	     break;
	    }
	    if(o)
	       sum++;
	}
	printf("%d\n",sum);
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值