B. Two Tables

题目:https://codeforces.com/contest/1555/problem/B

又是简单题,对我来说太难了,我是菜狗。。。下面是官方解,做了个学习笔记

You have an axis-aligned rectangle room with width W and height H, so the lower left corner is in point (0,0) and the upper right corner is in (W,H).

There is a rectangular table standing in this room. The sides of the table are parallel to the walls, the lower left corner is in (x1,y1), and the upper right corner in (x2,y2).

You want to place another rectangular table in this room with width w and height h with the width of the table parallel to the width of the room.

The problem is that sometimes there is not enough space to place the second table without intersecting with the first one (there are no problems with tables touching, though).

You can’t rotate any of the tables, but you can move the first table inside the room.

Example of how you may move the first table.
What is the minimum distance you should move the first table to free enough space for the second one?

Input
The first line contains the single integer t (1≤t≤5000) — the number of the test cases.

The first line of each test case contains two integers W and H (1≤W,H≤108) — the width and the height of the room.

The second line contains four integers x1, y1, x2 and y2 (0≤x1<x2≤W; 0≤y1<y2≤H) — the coordinates of the corners of the first table.

The third line contains two integers w and h (1≤w≤W; 1≤h≤H) — the width and the height of the second table.

Output
For each test case, print the minimum distance you should move the first table, or −1 if there is no way to free enough space for the second table.

Your answer will be considered correct if its absolute or relative error doesn’t exceed 10−6.

Example
input
5
8 5
2 1 7 4
4 2
5 4
2 2 5 4
3 3
1 8
0 3 1 6
1 5
8 1
3 0 6 1
5 1
8 10
4 5 7 8
8 5
output
1.000000000
-1
2.000000000
2.000000000
0.000000000

官方证明:

Firstly, let’s notice the next property: if two axis-aligned rectangles don’t intersect, then we can draw a vertical or horizontal line between them. In other words, either max(x1,x2)≤min(x3,x4) or max(x3,x4)≤min(x1,x2) if x1 and x2 are coordinates of the one rectangle and x3 and x4 of the other one (analogically, for y coordinates).

Now, suppose you want to move the first table by (dx,dy). Note that if in result they will be divided by vertical line then we can set dy=0 — they still will be divided, but the total distance will decrease. Analogically, if divided by horizontal line, we can set dx=0.

In other words, it’s always optimal to move the table either horizontally or vertically.

Let’s look at the case of horizontal move: at first, we need to check that both tables can fit in the room, or their total width w+(x2−x1)≤W. If yes, then we calculate the movement distance dx as follows: if we move the table right then there should be at least w to the left of it, or w≤x1+dx ⇔ dx≥w−x1. Since we want to minimize dx then we take dx=max(0,w−x1).

If we want to move the table left, then there should be at least w to the right, or x2−dx≤W−w ⇔ dx≥x2−(W−w), minimizing dx means taking dx=max(0,x2−(W−w)). So, the result is min(max(0,w−x1),max(0,x2−(W−w))).

The vertical case can be handled in the same manner, if h+(y2−y1)≤H then the result is min(max(0,h−y1),max(0,y2−(H−h))).

The answer is the minimum among all possible variants, or −1 if both cases are impossible.

AC代码:

#include <iostream>
#include <iomanip>
using namespace std;

const int inf = 1e9;

void solve() {

	int W, H;
	int x1, y1, x2, y2;
	int w, h;

	cin >> W >> H;
	cin >> x1 >> y1 >> x2 >> y2;
	cin >> w >> h;

	int ans = inf;

	if (x2 - x1 + w <= W) {

		ans = min(ans, max(0, w - x1)); //向右
		ans = min(ans, max(0, x2 - (W - w)));//向左 
	}

	if (y2 - y1 + h <= H) {

		ans = min(ans, max(0, h - y1));//向上 
		ans = min(ans, max(0, y2 - (H - h)));//向下 
	}

	if (ans == inf) {
		cout << -1 << endl;
	}
	else
		cout << (double)ans << endl;

}

int main() {

	ios_base::sync_with_stdio(0);
	cin.tie(0);

	int t; cin >> t;
	cout << fixed << setprecision(9);
	for (int i = 1; i <= t; i++) solve();

	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值