--- id: rect-geo title: "Rectangle Geometry" author: Darren Yao, Michael Cao, Benjamin Qi description: "Geometry problems on USACO Bronze are usually quite simple and limited to intersections and unions of squares or rectangles." frequency: 2 --- import { Problem } from "../models"; export const metadata = { problems: { blocked: [ new Problem("Bronze", "Blocked Billboard", "759", "Easy", false, ["rect"]), ], general: [ new Problem("Bronze", "Square Pasture", "663", "Intro", false, ["rect"]), new Problem("Bronze", "Blocked Billboard II", "783", "Easy", false, ["rect"]), new Problem("CF", "Div. 3 C - White Sheet", "contest/1216/problem/C", "Normal", false, ["rect"],"See this code (TODO; codeforces is down) for a nice implementation using the Java Rectangle class."), ] } }; Most only include two or three squares or rectangles, in which case you can simply draw out cases on paper. This should logically lead to a solution. ## Example: Blocked Billboard ### Naive Solution Since all coordinates are in the range $[-1000,1000]$, we can simply go through each of the $2000^2$ possible visible squares and check which ones are visible using nested for loops. ```cpp #include using namespace std; bool ok[2000][2000]; int main() { freopen("billboard.in","r",stdin); freopen("billboard.out","w",stdout); for (int i = 0; i < 3; ++i) { int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; x1 += 1000, y1 += 1000, x2 += 1000, y2 += 1000; for (int x = x1; x < x2; ++x) for (int y = y1; y < y2; ++y) { if (i < 2) ok[x][y] = 1; else ok[x][y] = 0; } } int ans = 0; for (int x = 0; x < 2000; ++x) for (int y = 0; y < 2000; ++y) ans += ok[x][y]; cout << ans << "\n"; } ``` Of course, this wouldn't suffice if the coordinates were up to $10^9$. ### Rectangle Class (Java) A useful class in `Java` for dealing with rectangle geometry problems (though probably overkill) is the built-in [`Rectangle`](https://docs.oracle.com/javase/8/docs/api/java/awt/Rectangle.html) class. To create a new rectangle, use the following constructor: ```java // creates a rectangle with upper-left corner at (x,y) with a specified width and height Rectangle newRect = new Rectangle(x, y, width, height); ``` The `Rectangle` class supports numerous useful methods. - `firstRect.intersects(secondRect)` checks if two rectangles intersect. - `firstRect.union(secondRect)` returns a rectangle representing the union of two rectangles. - `firstRect.contains(x, y)` checks whether the integer point $(x,y)$ exists in firstRect. - `firstRect.intersection(secondRect)` returns a rectangle representing the intersection of two rectangles. - what happens when intersection is empty? This class can often lessen the implementation needed in a lot of bronze problems and CodeForces problems. For example, here is a nice implementation of the problem ([editorial](http://www.usaco.org/current/data/sol_billboard_bronze_dec17.html)). ```java import java.awt.Rectangle; //needed to use Rectangle class import java.io.*; import java.util.*; public class blockedBillboard{ public static void main(String[] args) throws IOException{ Scanner sc = new Scanner(new File("billboard.in")); PrintWriter pw = new PrintWriter(new FileWriter("billboard.out")); int x1, y1, x2, y2; //the top left point is (0,0), so you need to do -y2 x1 = sc.nextInt(); y1 = sc.nextInt(); x2 = sc.nextInt(); y2 = sc.nextInt(); Rectangle firstRect = new Rectangle(x1, -y2, x2-x1, y2-y1); x1 = sc.nextInt(); y1 = sc.nextInt(); x2 = sc.nextInt(); y2 = sc.nextInt(); Rectangle secondRect = new Rectangle(x1, -y2, x2-x1, y2-y1); x1 = sc.nextInt(); y1 = sc.nextInt(); x2 = sc.nextInt(); y2 = sc.nextInt(); Rectangle truck = new Rectangle(x1, -y2, x2-x1, y2-y1); long firstIntersect = getArea(firstRect.intersection(truck)); long secondIntersect = getArea(secondRect.intersection(truck)); pw.println(getArea(firstRect) + getArea(secondRect) - firstIntersect - secondIntersect); pw.close(); } public static long getArea(Rectangle r){ if(r.getWidth() <= 0 || r.getHeight() <= 0){ return 0; } return (long)r.getHeight() * (long)r.getWidth(); } } ``` ```java import java.io.*; import java.util.*; class blockedBillboard{ public static void main(String[] args) throws IOException{ Scanner sc = new Scanner(new File("billboard.in")); PrintWriter pw = new PrintWriter(new FileWriter("billboard.out")); Rect a = new Rect(); Rect b = new Rect(); Rect t = new Rect(); int x1, y1, x2, y2; a.x1 = sc.nextInt(); a.y1 = sc.nextInt(); a.x2 = sc.nextInt(); a.y2 = sc.nextInt(); b.x1 = sc.nextInt(); b.y1 = sc.nextInt(); b.x2 = sc.nextInt(); b.y2 = sc.nextInt(); t.x1 = sc.nextInt(); t.y1 = sc.nextInt(); t.x2 = sc.nextInt(); t.y2 = sc.nextInt(); pw.println(area(a) + area(b) - intersect(a, t) - intersect(b, t)); pw.close(); sc.close(); } static int area(Rect r){ return (r.y2 - r.y1) * (r.x2 - r.x1); } static int intersect(Rect p, Rect q) { int xOverlap = Math.max(0, Math.min(p.x2, q.x2) - Math.max(p.x1, q.x1)); int yOverlap = Math.max(0, Math.min(p.y2, q.y2) - Math.max(p.y1, q.y1)); return xOverlap * yOverlap; } } class Rect{ int x1, y1, x2, y2; Rect(){ } } ``` ### Rectangle Class (C++) Unfortunately, C++ doesn't have a built in rectangle class, so you need to write the functions yourself. Here is the solution to Blocked Billboard written in C++ (thanks, Brian Dean!). ```cpp #include #include using namespace std; struct Rect{ int x1, y1, x2, y2; }; int area(Rect r){ return (r.y2 - r.y1) * (r.x2 - r.x1); } int intersect(Rect p, Rect q){ int xOverlap = max(0, min(p.x2, q.x2) - max(p.x1, q.x1)); int yOverlap = max(0, min(p.y2, q.y2) - max(p.y1, q.y1)); return xOverlap * yOverlap; } int main(){ ifstream cin ("billboard.in"); ofstream cout ("billboard.out"); Rect a, b, t; // billboards a, b, and the truck cin >> a.x1 >> a.y1 >> a.x2 >> a.y2; cin >> b.x1 >> b.y1 >> b.x2 >> b.y2; cin >> t.x1 >> t.y1 >> t.x2 >> t.y2; cout << area(a) + area(b) - intersect(a, t) - intersect(b, t) << endl; return 0; } ``` ## Problems