1. 程式人生 > >CCF NOI1043. 矩形分割 (C++)

CCF NOI1043. 矩形分割 (C++)

1043. 矩形分割

題目描述

平面上有一個大矩形,其左下角座標(0,0),右上角座標(R,R)。大矩形內部包含一些小矩形,小矩形都平行於座標軸且互不重疊。所有矩形的頂點都是整點。要求畫一根平行於y軸的直線x=k(k是整數) ,使得這些小矩形落在直線左邊的面積必須大於等於落在右邊的面積,且兩邊面積之差最小。並且,要使得大矩形在直線左邊的的面積儘可能大。注意:若直線穿過一個小矩形,將會把它切成兩個部分,分屬左右兩側。

輸入

第一行是整數R,表示大矩形的右上角座標是(R,R) (1 <= R <= 1,000,000)。
接下來的一行是整數N,表示一共有N個小矩形(0 < N <= 10000)。
再接下來有N 行。每行有4個整數,L,T, W 和 H, 表示有一個小矩形的左上角座標是(L,T),寬度是W,高度是H (0<=L,T <= R, 0 < W,H <= R). 小矩形不會有位於大矩形之外的部分。

輸出

輸出整數n,表示答案應該是直線 x=n。如果必要的話,x=R也可以是答案。

樣例輸入

1000
2
1 1 2 1
5 1 2 1

樣例輸出

5

資料範圍限制

C++

#include <iostream>
#include <cassert>
#include <vector>
#include <map>
#include <iterator>

using namespace std;

class Rectangle 
{
public:
    int L;  // top left x
int T; // top left y int W; // width int H; // height }; int main() { const int MAX_R = 1000000; const int MAX_N = 10000; vector<Rectangle> rect_vec; int R, N; cin >> R; assert(R>=1 && R<=MAX_R); cin >> N; assert(N>=0 && N<=
MAX_N); // ?? if (N <= 1) { cout << R << endl; return 0; } Rectangle rec; int min_x = R; int max_x = 0; for (int n=1; n<=N; n++) { cin >> rec.L >> rec.T >> rec.W >> rec.H; rect_vec.push_back(rec); min_x = min(rec.L, min_x); max_x = max(rec.L+rec.W, max_x); } int Sl; // left square of line x = k int Sr; // right square of line x = k map<int, int> Sdiff_k_map; for (int k=min_x; k<=max_x; k++) { Sl = 0; Sr = 0; for (int i=0; i<N; i++) { if (k <= rect_vec[i].L) { Sl += 0; Sr += rect_vec[i].W * rect_vec[i].H; } else if(k >= rect_vec[i].L+rect_vec[i].W) { Sl += rect_vec[i].W * rect_vec[i].H; Sr += 0; } else if (k > rect_vec[i].L && k < rect_vec[i].L+rect_vec[i].W) { Sl += (k - rect_vec[i].L) * rect_vec[i].H; Sr += (rect_vec[i].L+rect_vec[i].W - k) * rect_vec[i].H; } } Sdiff_k_map[Sl-Sr] = k; } map<int, int>::iterator iter; for(iter=Sdiff_k_map.begin(); iter!=Sdiff_k_map.end(); iter++) { if (iter->first >= 0) { cout << iter->second << endl; break; } } return 0; }