Hello coders, today we are going to solve Minimum Dual Area CodeChef Solution in C++, Java and Python.
Task
Given N points in a 2D space, find the minimum sum of areas of rectangles required to cover all the points given that we can use at most 2 non-overlapping rectangles whose sides can touch. The rectangles must be axis-aligned, meaning the sides are vertical and horizontal.
Input Format
- The first line contains an integer T, the number of test cases. Then the test cases follow.
- Each test case contains N+1 lines of input.
- The first line contains a single integer N, the number of points.
- The next N lines each contains two integers xi, yi, the coordinates of the i-th point.
Note: Points need not be distinct.
Output Format
For each test case, output in a single line the answer to the problem.
Constraints
- 1≤T≤105
- 1≤N≤105
- 0≤xi,yi≤109
- The sum of N over all test cases is at most 105
Subtasks
Subtask #1 (100 points): original constraints
Sample Input
3
1
100 100
4
1 100
100 100
100 1
1 1
5
1 100
100 100
100 1
1 1
50 50
Sample Output
0
0
4851
Explanation
Case 1: Since there is only one point, the minimum area of a rectangle to cover this point is 0.
Case 2: We can have rectangles as 2 opposite sides of the square. Since the width of the rectangles is 0, the total area is also 0.
Case 3: The optimal solution is with the rectangles having endpoints {(1,1),(100,1),(1,50),(100,50)} and {(1,100),(1,100),(100,100),(100,100)}. Therefore the total area is 49⋅99+0⋅99=4851
Solution – Minimum Dual Area CodeChef Solution
C++
#include <bits/stdc++.h> using namespace std; #define int long long int int32_t main() { ios_base::sync_with_stdio(false); int t; cin >> t; while (t--) { int n; cin >> n; vector<pair<int, int>> x; vector<pair<int, int>> y; multiset<int> X; multiset<int> Y; for (int i = 0; i < n; ++i) { int a, b; cin >> a >> b; x.push_back({a, b}); y.push_back({b, a}); X.insert(a); Y.insert(b); } sort(x.begin(), x.end()); sort(y.begin(), y.end()); int height1 = 0; int height2 = 0; int h1Max = 0; int h1Min = LONG_MAX; int area = LONG_MAX; for (int i = 0; i < n - 1; ++i) { h1Max = max(h1Max, x[i].second); h1Min = min(h1Min, x[i].second); height1 = h1Max - h1Min; auto it = Y.find(x[i].second); Y.erase(it); height2 = *Y.rbegin() - *Y.begin(); int newArea = (x[i].first - x[0].first) * height1 + (x[n - 1].first - x[i + 1].first) * height2; area = min(area, newArea); } int width1 = 0; int width2 = 0; int w1Max = 0; int w1Min = LONG_MAX; for (int i = 0; i < n - 1; ++i) { w1Max = max(w1Max, y[i].second); w1Min = min(w1Min, y[i].second); width1 = w1Max - w1Min; auto it = X.find(y[i].second); X.erase(it); width2 = *X.rbegin() - *X.begin(); int newArea = (y[i].first - y[0].first) * width1 + (y[n - 1].first - y[i + 1].first) * width2; area = min(area, newArea); } if (area == LONG_MAX) area = 0; cout << area << endl; } return 0; }
Python
def area(rectangle): [A,B] = rectangle return abs(B[0] - A[0]) * abs(B[1] - A[1]) def solve(points): if len(points)<=2: return 0 points_x = sorted(points, key = lambda x: x[0]) ymx = {} for p in points_x: if p[0] not in ymx: ymx[p[0]] = [p[1], p[1]] continue if p[1] < ymx[p[0]][0]: ymx[p[0]][0] = p[1] elif p[1] > ymx[p[0]][1]: ymx[p[0]][1] = p[1] y_right = {points_x[-1][0]: ymx[points_x[-1][0]]} for i in range(N-2,-1, -1): y_right[points_x[i][0]] = [min(y_right[points_x[i+1][0]][0], ymx[points_x[i][0]][0]), max(y_right[points_x[i+1][0]][1], ymx[points_x[i][0]][1])] r1_x = [points_x[0][0],points_x[0][0]] r2_x = [points_x[-1][0], points_x[-1][0]] r1_y = [ymx[points_x[0][0]][0],ymx[points_x[0][0]][1]] r2_y = [y_right[points_x[-1][0]][0],y_right[points_x[-1][0]][1]] area_max = float('inf') for i in range(N-1): r1_x[1] = points_x[i][0] r2_x[0] = points_x[i+1][0] if r1_y[0] > ymx[points_x[i][0]][0]: r1_y[0] = ymx[points_x[i][0]][0] if r1_y[1] < ymx[points_x[i][0]][1]: r1_y[1] = ymx[points_x[i][0]][1] r2_y = y_right[points_x[i+1][0]] new_area = area([[r1_x[0],r1_y[0]],[r1_x[1],r1_y[1]]]) + area([[r2_x[0],r2_y[0]],[r2_x[1],r2_y[1]]]) if new_area < area_max: area_max = new_area points = [[y,x] for [x,y] in points] points_x = sorted(points, key = lambda x: x[0]) ymx = {} for p in points_x: if p[0] not in ymx: ymx[p[0]] = [p[1], p[1]] continue if p[1] < ymx[p[0]][0]: ymx[p[0]][0] = p[1] elif p[1] > ymx[p[0]][1]: ymx[p[0]][1] = p[1] y_right = {points_x[-1][0]: ymx[points_x[-1][0]]} for i in range(N-2,-1, -1): y_right[points_x[i][0]] = [min(y_right[points_x[i+1][0]][0], ymx[points_x[i][0]][0]), max(y_right[points_x[i+1][0]][1], ymx[points_x[i][0]][1])] r1_x = [points_x[0][0],points_x[0][0]] r2_x = [points_x[-1][0], points_x[-1][0]] r1_y = [ymx[points_x[0][0]][0],ymx[points_x[0][0]][1]] r2_y = [y_right[points_x[-1][0]][0],y_right[points_x[-1][0]][1]] full_rect = [[points_x[0][0], y_right[points[0][0]][0]], [points_x[-1][0],y_right[points[0][0]][1]]] for i in range(N-1): r1_x[1] = points_x[i][0] r2_x[0] = points_x[i+1][0] if r1_y[0] > ymx[points_x[i][0]][0]: r1_y[0] = ymx[points_x[i][0]][0] if r1_y[1] < ymx[points_x[i][0]][1]: r1_y[1] = ymx[points_x[i][0]][1] r2_y = y_right[points_x[i+1][0]] new_area = area([[r1_x[0],r1_y[0]],[r1_x[1],r1_y[1]]]) + area([[r2_x[0],r2_y[0]],[r2_x[1],r2_y[1]]]) if new_area < area_max: area_max = new_area return area_max for _ in range(int(input())): N = int(input()) points = [[int(x) for x in input().split()] for i in range(N)] print(solve(points))
Java
import java.io.*; import java.util.*; class Point{ public long x; public long y; } public class Main { static void print(ArrayList<Long> x) { return; } static class Reader { static BufferedReader reader; static StringTokenizer tokenizer; /** call this method to initialize reader for InputStream */ static void init(InputStream input) { reader = new BufferedReader(new InputStreamReader(input)); tokenizer = new StringTokenizer(""); } /** get next word */ static String next() throws IOException { while (!tokenizer.hasMoreTokens()) { // TODO add check for eof if necessary tokenizer = new StringTokenizer(reader.readLine()); } return tokenizer.nextToken(); } static int nextInt() throws IOException { return Integer.parseInt(next()); } static String nextLine() throws IOException { return reader.readLine(); } static long nextLong() throws IOException { return Long.parseLong(next()); } static double nextDouble() throws IOException { return Double.parseDouble(next()); } } public static void main(String[] args) throws IOException { Reader.init(System.in); int t = Reader.nextInt(); while(t-- > 0) { solve(); } } public static void solve() throws IOException { int N = Reader.nextInt(); Point point[] = new Point[N]; long x,y; for(int i = 0 ; i < N ; i++) { x = Reader.nextInt(); y = Reader.nextInt(); point[i] = new Point(); point[i].x=x; point[i].y=y; } HashMap<Long, Long> mnX = new HashMap<>(); HashMap<Long , Long> mxX = new HashMap<>(); HashMap<Long , Long> mnY = new HashMap<>(); HashMap<Long , Long> mxY = new HashMap<>(); for(Point p : point) { if(!(mnY.containsKey(p.x) || mxY.containsKey(p.x))) { mnY.put(p.x , p.y); mxY.put(p.x , p.y); } else { mnY.put(p.x, Math.min(p.y, mnY.get(p.x))); mxY.put(p.x, Math.max(p.y, mxY.get(p.x))); } if(!(mnX.containsKey(p.y) || mxX.containsKey(p.y))) { mnX.put(p.y , p.x); mxX.put(p.y , p.x); } else { mnX.put(p.y, Math.min(p.x, mnX.get(p.y))); mxX.put(p.y, Math.max(p.x, mxX.get(p.y))); } } ArrayList<Long> x_cord = new ArrayList<>(); ArrayList<Long> y_cord = new ArrayList<>(); for(long key : mxX.keySet()) { y_cord.add(key); print(y_cord); } for(long key : mxY.keySet()) { x_cord.add(key); print(x_cord); } Collections.sort(x_cord); Long bottom_y = Long.MAX_VALUE; Long top_y = Long.MIN_VALUE; print(x_cord); Long left_most_x = x_cord.get(0); Long ar_reg; ArrayList<Long> lf_sm = new ArrayList<>(); ArrayList<Long> right_area=new ArrayList<>(); right_area.add(x_cord.get(0)*y_cord.get(0)); for(Long curr_x: x_cord) { top_y = Math.max(top_y , mxY.get(curr_x)); bottom_y = Math.min(bottom_y, mnY.get(curr_x)); Long t1=top_y-bottom_y; Long t2=curr_x - left_most_x; right_area.add(y_cord.get(0)*x_cord.get(0)); ar_reg = Math.abs(t1*t2); lf_sm.add(ar_reg); } ArrayList<Long> rg_sm = new ArrayList<>(); ArrayList<Long> left_area=new ArrayList<>(); bottom_y = Long.MAX_VALUE; top_y = Long.MIN_VALUE; left_area.add(x_cord.get(0)*y_cord.get(0)); left_most_x = x_cord.get(x_cord.size() - 1); int nik = x_cord.size()- 1; while(nik>=0) { Long curr_x = x_cord.get(nik); bottom_y = Math.min(bottom_y, mnY.get(curr_x)); top_y = Math.max(top_y, mxY.get(curr_x)); Long t3=top_y-bottom_y; Long t4=curr_x - left_most_x; ar_reg = Math.abs(t3*t4); rg_sm.add(ar_reg); nik--; } int x_len = x_cord.size(); Long mnDualAr = Long.MAX_VALUE; int l=0; while( l < x_len){ int j = x_len - l - 2; if(j<0) { j=0; } Long curr_area = lf_sm.get(l) + rg_sm.get(j); mnDualAr = Math.min(mnDualAr, curr_area); l++; } Collections.sort(y_cord); lf_sm = new ArrayList<>(); rg_sm = new ArrayList<>(); Long left_x = Long.MAX_VALUE; Long right_x = Long.MIN_VALUE; //Collections.sort(y_cord); Long bottom_most_y = y_cord.get(0); for(Long curr_y : y_cord) { //print(lf_sm); left_x = Math.min(left_x, mnX.get(curr_y)); right_x = Math.max(right_x, mxX.get(curr_y)); Long t5=right_x-left_x; Long t6=bottom_most_y - curr_y; ar_reg = Math.abs(t5*t6); lf_sm.add(ar_reg); Long temp3=lf_sm.get(0); Long y3=lf_sm.get(0); } left_x = Long.MAX_VALUE; right_x = Long.MIN_VALUE; bottom_most_y = y_cord.get(y_cord.size() - 1); for(int i = y_cord.size()- 1 ; i>=0 ; i--) { Long curr_y = y_cord.get(i); //print(y_cord); left_x = Math.min(left_x, mnX.get(curr_y)); right_x = Math.max(right_x, mxX.get(curr_y)); Long t7=right_x-left_x; Long t8=curr_y - bottom_most_y; ar_reg = Math.abs(t7*t8); rg_sm.add(ar_reg); Long temp2=rg_sm.get(0); Long y2=lf_sm.get(0); } int y_len = y_cord.size(); for(int i = 0 ; i < y_len ; i++) { int j = y_len - i - 2; if(j<0) j = 0; Long curr_area = lf_sm.get(i) + rg_sm.get(j); Long t1=rg_sm.get(0); Long t2=lf_sm.get(0); Long min_t=Math.min(t1,t2); mnDualAr = Math.min(mnDualAr, curr_area); } System.out.println(mnDualAr); } }
Disclaimer: The above Problem (Minimum Dual Area) is generated by CodeChef but the Solution is Provided by CodingBroz. This tutorial is only for Educational and Learning Purpose.