题目描述 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 Description
n k
xl y1
x2 y2
... ...
xn yn (0<=xi,yi<=500)
输出描述 Output Description
一个整数,即满足条件的最小的矩形面积之和。
样例输入 Sample Input
4 2
1 1
2 2
3 6
0 7
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
k<4
官方是k<=4,但是标程解法在k=4时是有反例的。官方的数据也没有出现k=4的情况
/* 由于k<=3,所以可以分着做 */ #include<cstdio> #include<iostream> #include<algorithm> #include<cstdlib> #define N 52 #define INF 10000000 using namespace std; int n,m; struct node { int x,y; };node a[N]; bool cmp1(const node&s1,const node&s2) { return s1.x<s2.x; } bool cmp2(const node&s1,const node&s2) { return s1.y<s2.y; } int work1(int s,int t) { int mnx=INF,mxx=0,mny=INF,mxy=0; for(int i=s;i<=t;i++) { mnx=min(mnx,a[i].x);mxx=max(mxx,a[i].x); mny=min(mny,a[i].y);mxy=max(mxy,a[i].y); } return (mxx-mnx)*(mxy-mny); } int work2(int s,int t) { int minn=INF; sort(a+s,a+t+1,cmp1);//从左向右分 for(int i=s+1;i<=t-2;i++) if(a[i].x!=a[i+1].x) minn=min(minn,work1(s,i)+work1(i+1,t)); sort(a+s,a+t+1,cmp2);//从上向下分 for(int i=s+1;i<=t-2;i++) if(a[i].y!=a[i+1].y) minn=min(minn,work1(s,i)+work1(i+1,t)); return minn; } int work3(int s,int t) { int minn=INF; sort(a+s,a+t+1,cmp1); for(int i=s+1;i<=t-4;i++) if(a[i].x!=a[i+1].x) minn=min(minn,work1(s,i)+work2(i+1,t)); for(int i=s+3;i<=t-2;i++) if(a[i].y!=a[i+1].y) minn=min(minn,work2(s,i)+work1(i+1,t)); sort(a+s,a+t+1,cmp2); for(int i=s+1;i<=t-4;i++) if(a[i].x!=a[i+1].x) minn=min(minn,work1(s,i)+work2(i+1,t)); for(int i=s+3;i<=t-2;i++) if(a[i].y!=a[i+1].y) minn=min(minn,work2(s,i)+work1(i+1,t)); return minn; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y); if(m==1)printf("%d",work1(1,n)); if(m==2)printf("%d",work2(1,n)); if(m==3)printf("%d",work3(1,n)); return 0; }