CCF NOI1043. 矩形分割 (C++)
阿新 • • 發佈:2018-12-11
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;
}