华为机试题-从(0,0)开始,计算绘图面积-Java
代码在最后面
1 题目描述
绘图机器的绘图笔初始位置在原点(0,0),机器启动后按照以下规则来进行绘制直线。
- 尝试沿着横线坐标正向绘制直线直到给定的终点E。
- 期间可以通过指令在纵坐标轴方向进行偏移,offset Y为正数表示正向偏移,为负数表示负向偏移。
现在给定的横坐标终点值E以及若干条绘制指令,请计算绘制的直线和横坐标轴以及x=E
的直线组成的图形面积。
2 输入描述
首行为两个整数N和E,表示有N条指令,机器运行的横坐标终点值E。接下来N行每行两个整数表示一条绘制指令X offsetY。用例保证横坐标X以递增排序
的方式出现,且不会出现相同横坐标X。
取值范围:
0<N<=10000
0<=X<=E<=20000
-10000<=offsetY<=10000
3 输出描述
一个整数表示计算得到的面积用例保证结果范围在0到4294967295之内。
4 示例
4.1 示例1
输入
4 10
1 1
2 1
3 1
4 -2
输出
12
解释:
根据上述指令,绘制图形如下图所示:
如图,蓝色和红色围起来的,1+2+3+6 = 12
4.2 示例2
输入
2 4
0 1
2 -2
输出
4
解释:
根据上述指令,绘制图形如下图所示:
2 + 2 = 4
5 代码解题
思路:每个图形可以切割为多个矩形,然后求矩形面积和即可。例如示例1,可以做如下切割:
可以观察到,总面积 = 矩形1 + 矩形2 + 矩形3 + 矩形4。
每个矩形的面积取决于左上角的点和右上角的点【如果在X轴下方,则是左下和右下】,而根据题意,会提供X offset Y,也就是说,后一个点的X是右上点的x值坐标,前一个点的X是左上点的x值坐标,整体高度取决于前一个点的高度。
例如:
1 1 // 第一次输入
2 1 // 第二次输入
4 1 // 第三次输入
连续起来,可以得到第一次和第二次输入的X轴宽度为 2 - 1 = 1,高度取第一个点的输入值为 1。依次类推,第二个矩形X轴宽 2 = 4 - 2,高为2【理解题意,是累加的】。
由此,可得整体解题思路为,记每次输入的前一个点的坐标为(x0, y0),当前输入的值为 (w, h),两点之间的和X轴组成的面积 = (w - X0) * abs(y0)
,更新x0 = w; y0 = y0 + h
即可得下次输入时的上一个点信息。同时考虑到最终点E的闭合问题,默认增加一次最后输入值为 (E,-y0),即满足x = E
的线信息。
但是实际计算过程中,我们只需要左上角的点即可,因为相邻两个矩形之间,是紧凑的,后一个点的Y值并不会考虑在计算范围内。
5.1 解法一
记录所有输入的点,然后for
循环算出面积求和
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
String[] split = line.split(" ");
final int N = Integer.parseInt(split[0]);
final int E = Integer.parseInt(split[1]);
int[][] points = new int[N + 2][2];
// 录入起点
points[0] = new int[]{0, 0};
// 录入终点,最后一个点的右上角不用考虑,因为用不到,所以用 0 代替
points[N + 1] = new int[]{E, 0};
for (int i = 1; i < N + 1; i++) {
String c = scanner.nextLine();
String[] arr = c.split(" ");
int x = Integer.parseInt(arr[0]);
int y = Integer.parseInt(arr[1]) + points[i - 1][1];
points[i] = new int[]{x, y};
}
scanner.close();
long area = calcArea(points);
System.out.println(area);
}
// 根据点,计算面积
public static long calcArea(int[][] points){
int len = points.length;
long area = 0;
for (int i = 1; i < len; ++i) {
area += (long) (points[i][0] - points[i - 1][0]) * Math.abs(points[i - 1][1]);
}
return area;
}
}
解法二
其实没有必要罗列这些点,可以在每次输入的时候,就直接计算面积,然后累加。优化上面的代码,如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
String[] split = line.split(" ");
final int N = Integer.parseInt(split[0]);
final int E = Integer.parseInt(split[1]);
long area = 0;
int x = 0, y = 0;
for (int i = 1; i < N + 1; i++) {
String c = scanner.nextLine();
String[] arr = c.split(" ");
int inputX = Integer.parseInt(arr[0]);
int inputY = Integer.parseInt(arr[1]);
area += (long) (inputX - x) * Math.abs(y);
x = inputX;
y += inputY;
}
scanner.close();
System.out.println(area);
}
}
原文地址:https://blog.csdn.net/qq_44503987/article/details/140375702
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!