矩形覆盖(codevs 1101)

题目描述 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;
}
View Code

 

posted @ 2016-10-04 21:50  karles~  阅读(305)  评论(0编辑  收藏  举报