第七届蓝桥杯Java/A组 第五题
题目:
广场舞 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 请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。 所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。 注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。 注意:主类的名字必须是:Main,否则按无效代码处理。
思路:
1.找到图形整体所在的X区间
2.将图像的顶点存在一个set集合中,由于不懂如何在set中存二元坐标,所以定义了内部类point 含有两个属性x,y 。
3. 由顶点坐标依次遍历每一条边,找到每一条线段,在X区间的每一个x值对应的y值, 并将其存在map 中
4. 然后通过y值上下的减法,得到每个x值有效的坐标点的数量
5.通过坐标点的数量求小矩形的面积: 两个相邻的x值组成的坐标块数量= min(两个有效坐标的的数量)-1;
6.加和得出result
代码如下:
package come_on; import java.util.*; public class Fifth { static int x_start; static int x_end; static class point{ float x; float y; public point(float x, float y){ this.x=x; this.y=y; } } public static void main(String args[]){ ArrayList<point> list = new ArrayList<>(); Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); scanner.nextLine(); for(int i=0;i<n;i++){ point points = new point(scanner.nextInt(),scanner.nextInt()); scanner.nextLine(); list.add(points); } Set<point> set = new HashSet<>(); x_start = (int)list.get(0).x; x_end= (int)list.get(0).x; for(int i=0;i<5;i++){ float x1 = list.get(i).x; float y1 = list.get(i).y; float x2,y2; if(x_start>=(int)x1) x_start= (int)x1; if(x_end<=(int)x1) x_end= (int)x1; if(i!=list.size()-1){ x2 = list.get(i+1).x; y2 = list.get(i+1).y; } else { x2 = list.get(0).x; y2 = list.get(0).y; } for(float x0=Math.min(x1,x2);x0<Math.max(x1,x2);x0++){ float y0 =(y1-y2)/(x1-x2)*(x0-x1)+y1; point point_x = new point(x0,y0); set.add(point_x); } } Map<Integer,Integer> map = new TreeMap<>(); map.put(x_start,0); map.put(x_end,0); for(point p:set){ float x0 = p.x; float y0 =p.y; for(point p0:set){ float x00 =p0.x; float y00 =p0.y; if(x00==x0&&y0>y00){ map.put((int)x0,(int)((int)y0-y00)+1); } } } int result =0; for(int i =x_start;i<x_end-1;i++){ if(map.get(i)!=null&&map.get(i+1)!=null){ int q = Math.min(map.get(i),map.get(i+1))-1; if(q>=0) result+=q; } } System.out.println(result); } }
这道题没有查看答案,做了大概有四个小时,感觉自己的不足还很多,继续加油。
同样还有个问题没有搞懂(百度也没有查到),希望大神指点一二:
set集合用迭代器输出自定义对象point的时候,打印出来的是地址,但是用for循环输出的时候就没有这个问题,不知道是为什么。
以及还有什么更好的想法或者思路欢迎交流讨论。