【Description】
在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示。例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2),p3(3,6),P4(0,7),见图一。
这些点可以用 k 个矩形(1<=k<4)全部覆盖,矩形的边平行于坐标轴。当 k=2 时,可用如图二的两个矩形 sl,s2 覆盖,s1,s2 面积和为 4。问题是当 n 个点坐标和 k 给出后,怎样才能使得覆盖所有点的 k 个矩形的面积之和为最小呢。约定:覆盖一个点的矩形面积为 0;覆盖平行于坐标轴直线上点的矩形面积也为0。各个矩形必须完全分开(边线与顶点也都不能重合)。
【Input】
键盘输人文件名。文件格式为
n k
xl y1
x2 y2
… …
xn yn (0<=xi,yi<=500)
【Output】
输出至屏幕。格式为:
一个整数,即满足条件的最小的矩形面积之和。
【Sample Input】
4 2
1 1
2 2
3 6
0 7
【Sample Output】
4
【Data Size and Hint】
k<4
官方是k<=4,但是标程解法在k=4时是有反例的。官方的数据也没有出现k=4的情况
【Solution】
数据范围很小,这样搜索便是一个不错的方法。
参考代码如下:
type point =
record
x,y:longint;
end;
rectangle =
record
x1,x2,y1,y2:longint;
end;
var n,k,ans:longint;
p:array[1..51] of point;
a:array[1..3] of rectangle;
function max(x,y:longint):longint;
begin if x>y then exit(x) else exit(y); end;
function min(x,y:longint):longint;
begin if x<y then exit(x) else exit(y); end;
procedure init; //读入初始化
var i:longint;
begin
readln(n,k);
for i:=1 to n do readln(p[i].x,p[i].y);
ans:=maxlongint;
fillchar(a,sizeof(a),255);
end;
function calc:longint; //计算矩形面积
var i:longint;
begin
calc:=0;
for i:=1 to k do
with a[i] do begin
if x1=-1 then continue;
inc(calc,(x2-x1)*(y2-y1));
end;
end;
procedure edit(x:point; var r:rectangle); //修改矩形大小
begin
if r.x1=-1 then
with r do begin
x1:=x.x; x2:=x.x; y1:=x.y; y2:=x.y;
exit;
end;
if x.x<r.x1 then r.x1:=x.x;
if x.x>r.x2 then r.x2:=x.x;
if x.y<r.y1 then r.y1:=x.y;
if x.y>r.y2 then r.y2:=x.y;
end;
function intersect(a,b:rectangle):boolean; //判断两个矩形是否相交
var x1,x2,y1,y2:longint;
begin
x1:=max(a.x1,b.x1);
x2:=min(a.x2,b.x2);
y1:=max(a.y1,b.y1);
y2:=min(a.y2,b.y2);
intersect:=not((x1>x2) or (y1>y2));
end;
function judge:boolean; //判断是否存在相交矩形
var i,j:longint;
begin
judge:=true;
for i:=1 to k do begin
if a[i].x1=-1 then continue;
for j:=1 to k do begin
if a[j].x1=-1 then continue;
if i=j then continue;
if intersect(a[i],a[j]) then exit(false);
end;
end;
end;
procedure dfs(dep:longint); //深度优先搜索
var i,tmp:longint;
tmpr:rectangle;
begin
tmp:=calc;
if dep=n+1 then begin
if tmp<ans then ans:=tmp;
exit;
end;
if tmp>ans then exit;
for i:=1 to k do begin
tmpr:=a[i];
edit(p[dep],a[i]);
if not judge then begin
a[i]:=tmpr; continue;
end;
dfs(dep+1);
a[i]:=tmpr;
end;
end;
begin
init;
dfs(1);
writeln(ans);
end.