題解 P1034 【矩形覆蓋】
阿新 • • 發佈:2018-11-07
題面
在平面上有n個點(n≤50),每個點用一對整數座標表示。例如:當n=4時,4個點的座標分另為:p1(1,1),p2(2,2),p3(3,6),P4(0,7),見圖一。
這些點可以用k個矩形(1≤k≤4)全部覆蓋,矩形的邊平行於座標軸。當k=2時,可用如圖二的兩個矩形S1,s2覆蓋,81,S2面積和為4。問題是當n個點座標和k給出後,怎樣才能使得覆蓋所有點的k個矩形的面積之和為最小呢?
約定:覆蓋一個點的矩形面積為0;覆蓋平行於座標軸直線上點的矩形面積也為0。各個矩形必須完全分開(邊線與頂點也都不能重合)。
題意
有n個點,找k個矩形包含所有點,使k個矩形和麵積和最小。
題解
這道題剛拿到手裡的時候是挺棘手的,但是我們看資料範圍的大小,是可以暴力列舉的,所以我們可以嘗試一下暴力列舉。
建圖操作
maps用來存圖
ss用來存構建的矩形
立flag來統計這種矩形是否建過
資料最大是4塊矩形,可以開小陣列
struct maps
{
int x,y;
} mapp[51];
struct ss
{
int l,r,u,d;
bool flag;
} p[5];
判斷操作
judge函式列舉四種不成立的情況
in函式判斷範圍,便於書寫judge函式
bool in(ss a, int x, int y) { if (x>=a.l&&x<=a.r&&y>=a.d&&y<=a.u) return 1; return 0; } bool judge(ss a, ss b) { if (in(a,b.l,b.u)) return 1; if (in(a,b.l,b.d)) return 1; if (in(a,b.r,b.u)) return 1; if (in(a,b.r,b.d)) return 1; return 0; }
dfs操作
構建好m個矩形
計算面積和
每次存最小值
搜完結束
void dfs(int num) { int value=0; for (int i=1; i<=m; i++) { if (p[i].flag) { for (int j=i+1; j<=m; j++) if (judge(p[i],p[j])) return; } value+=(p[i].r-p[i].l)*(p[i].u-p[i].d); } if (value>=ans) return; if (num>n){ ans=value; return; } for (int i=1; i<=m; i++) { ss tmp=p[i]; if (p[i].flag==0) { p[i].flag=1; p[i].l=p[i].r=mapp[num].x; p[i].u=p[i].d=mapp[num].y; dfs(num+1); p[i]=tmp; break; } else { p[i].r=max(p[i].r,mapp[num].x); p[i].l=min(p[i].l,mapp[num].x); p[i].u=max(p[i].u,mapp[num].y); p[i].d=min(p[i].d,mapp[num].y); dfs(num+1); p[i]=tmp; } } }
程式碼
#include<cstdio>
#include<iostream>
using namespace std;
struct maps
{
int x,y;
} mapp[51];
struct ss
{
int l,r,u,d;
bool flag;
} p[5];
int n,m,ans=0x7f7f7f7f;
bool in(ss a, int x, int y)
{
if (x>=a.l&&x<=a.r&&y>=a.d&&y<=a.u) return 1;
return 0;
}
bool judge(ss a, ss b)
{
if (in(a,b.l,b.u)) return 1;
if (in(a,b.l,b.d)) return 1;
if (in(a,b.r,b.u)) return 1;
if (in(a,b.r,b.d)) return 1;
return 0;
}
void dfs(int num)
{
int value=0;
for (int i=1; i<=m; i++)
{
if (p[i].flag)
{
for (int j=i+1; j<=m; j++)
if (judge(p[i],p[j])) return;
}
value+=(p[i].r-p[i].l)*(p[i].u-p[i].d);
}
if (value>=ans) return;
if (num>n){
ans=value;
return;
}
for (int i=1; i<=m; i++)
{
ss tmp=p[i];
if (p[i].flag==0)
{
p[i].flag=1;
p[i].l=p[i].r=mapp[num].x;
p[i].u=p[i].d=mapp[num].y;
dfs(num+1); p[i]=tmp;
break;
}
else
{
p[i].r=max(p[i].r,mapp[num].x);
p[i].l=min(p[i].l,mapp[num].x);
p[i].u=max(p[i].u,mapp[num].y);
p[i].d=min(p[i].d,mapp[num].y);
dfs(num+1);
p[i]=tmp;
}
}
}
int main(void)
{
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) scanf("%d%d",&mapp[i].x,&mapp[i].y);
dfs(1);
printf("%d",ans);
return 0;
}