广场舞第七届蓝桥杯

原创出自于点击打开链接

在此对作者代码及其思路写出自己的见解。

LQ市的市民广场是一个多边形,广场上铺满了大理石的地板砖。
地板砖铺得方方正正,就像坐标轴纸一样。
以某四块砖相接的点为原点,地板砖的两条边为两个正方向,一块砖的边长为横纵坐标的单位长度,则所有横纵坐标都为整数的点都是四块砖的交点(如果在广场内)。
广场的砖单调无趣,却给跳广场舞的市民们提供了绝佳的参照物。每天傍晚,都会有大批市民前来跳舞。
舞者每次都会选一块完整的砖来跳舞,两个人不会选择同一块砖,如果一块砖在广场边上导致缺角或者边不完整,则没人会选这块砖。(广场形状的例子参考【图1.png】)
现在,告诉你广场的形状,请帮LQ市的市长计算一下,同一时刻最多有多少市民可以在广场跳舞。
【输入格式】
输入的第一行包含一个整数n,表示广场是n边形的(因此有n个顶点)。
接下来n行,每行两个整数,依次表示n边形每个顶点的坐标(也就是说广场边缘拐弯的地方都在砖的顶角上。数据保证广场是一个简单多边形。
【输出格式】
输出一个整数,表示最多有多少市民可以在广场跳舞。
【样例输入】
5
3 3
6 4
4 1
1 -1
0 4
【样例输出】
7
【样例说明】
广场如图1.png所示,一共有7块完整的地板砖,因此最多能有7位市民一起跳舞。
【数据规模与约定】
对于30%的数据,n不超过100,横纵坐标的绝对值均不超过100。
对于50%的数据,n不超过1000,横纵坐标的绝对值均不超过1000。
对于100%的数据,n不超过1000,横纵坐标的绝对值均不超过100000000(一亿)。
资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

思路:

1: 定义点、线结构体,录入点(前提是点是有序录入 顺时针或者逆时针),然后两点构成一条线,n个点n条线 
2:算出最左、最右的横坐标值 minx maxx 
3:当x = minx+1 
(1)遍历每一条线,如果这条线与x = minx+1这条线有交点,就把交点处的纵坐标算出,并用一个数组buf记录这条线还有纵坐标
(2)对buf数组进行排序,以记录的纵坐标的大小进行从小到大的排序;
(3)对于排完序的buf数组,下标为0对应的线和下标为1对应的线在minx到minx+1之间所构成的封闭的空间是属于区域内部的;下标为1与下标为2所构成的空间属于外部;2-3是内部 以此类推 
(4)针对于buf[0] 我们需要求出线在x=minx处的纵坐标(并向上取整)y11,x = minx+1处的纵坐标为(向上取整)y12
y1 =  max(y11,y12);
 对于buf[1],我们在求x = minx 和 x = minx+1 处的纵坐标时向下取整
 y2 = min(y21,y22); 
 if(y2-y1>0){
  sum += y2-y1;
 }
4:x= x+1;循环第三步 
5:在做的时候,考虑到又可能有两条线 与x = i这条线交于一点(i,y)
在排序的时候有可能导致这两条线的位置互换,从而得出错误答案

我们记录线在x = i-0.5处的纵坐标,这样纵坐标就不会重复了(纵坐标的值关系到线的位置) 

#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
struct Point {/*--点--*/
	int x;
	int y;
}P[1010];
struct Line{/*--线:两个点构成--*/
	Point a;
	Point b;
}L[1010];
struct I_Y{/*--线的下标,还有对应的纵坐标--*/
	int index;
	double y;
}ans[1010];
int N,sum = 0;//点的总数,方块的总数 
bool cmp (struct I_Y a,struct I_Y b)
{
	return a.y<b.y;
}
int max(int a,int b)
{
	return a>b?a:b;
}
int min(int a,int b){
	return a>b?b:a;
}
double F_y(struct Line l,double x)//求线l经过横坐标为x的点的纵坐标 
{
	double x1 = fabs(l.a.x-l.b.x);
	double x2 = fabs(x - l.a.x);
	double y = (l.b.y-l.a.y)*x2/x1 + l.a.y;
	return y;
}
void solve()
{
	int minx ,maxx,i,j,k,count,ax,bx;
	minx = P[0].x;
	maxx = P[0].x;
	for(i=0;i<N;i++){//寻找最小、大横坐标 
		if(P[i].x>maxx){
			maxx = P[i].x;
		}
		if(P[i].x<minx){
			minx = P[i].x; 
		}
	}
	for(i=minx+1;i<=maxx;i++){
		count = 0;
		for(j=0;j<N;j++){
			ax = L[j].a.x;
			bx = L[j].b.x;
			if((ax<=i-1&&bx>=i) || (ax>=i && bx <=i-1)){//当这条线和x = i有交点时 
				ans[count].index = j;
				ans[count].y = F_y(L[j],(i+i-1)/2.0); 
				count++;
			}
		} 
		sort(ans,ans+count,cmp);
		for(k=0;k<count/2;k++){//向上取整函数 double ceil(double x) 向下取整是double floor(double x) 在#include<math.h>中 
			int y1 = max((int)ceil(F_y(L[ans[k*2].index],i)),(int)ceil(F_y(L[ans[k*2].index],i-1)));
			int y2 = min((int)floor(F_y(L[ans[k*2+1].index],i)),(int)floor(F_y(L[ans[k*2+1].index],i-1)));
		//	printf("y1 = %d ,y2 = %d\n",y1,y2);
			if(y2-y1>0){
				sum+=y2-y1;
			}
		}
	}
	cout<<sum<<endl;
}
int main() 
{
	int x,y;
	cin>>N;
	for(int i=0;i<N;i++){
		cin>>x>>y;
		P[i].x = x;
		P[i].y = y;
	}
	L[0].a = P[0];
	L[0].b = P[N-1];
	for(int i=1;i<N;i++){
		L[i].a = P[i];
		L[i].b = P[i-1];
	}
	solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39562286/article/details/80033097