题目描述
在平面上有 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。各个矩形必须完全分开(边线与顶点也都不能重合)。
输入输出格式
输入格式:
n k xl y1 x2 y2 ... ...
xn yn (0<=xi,yi<=500)
输出格式:
输出至屏幕。格式为:
一个整数,即满足条件的最小的矩形面积之和。
输入输出样例
输入样例#1:
4 2
1 1
2 2
3 6
0 7
输出样例#1:
4
思路:深搜,枚举每个点放在哪个矩形中
吐槽:(╯‵□′)╯︵┻━┻,cogs上第6组数据竟然是错误的,害我调试了辣么久。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,k,ans=0x7f7f7f7f,val; struct nond{ int x,y; }v[60]; struct none{ int l,r,u,d; //记录这个矩形的四极。 bool falg; //判断这个矩形内有没有点 }f[5]; int judge(int i,int j){ if(f[i].l<=f[j].l&&f[i].r>=f[j].l&&f[i].d>=f[j].d&&f[i].u<=f[j].d) return 1; if(f[i].l<=f[j].r&&f[i].r>=f[j].r&&f[i].d>=f[j].d&&f[i].u<=f[j].d) return 1; if(f[i].l<=f[j].l&&f[i].r>=f[j].l&&f[i].d>=f[j].u&&f[i].u<=f[j].u) return 1; if(f[i].l<=f[j].r&&f[i].r>=f[j].r&&f[i].d>=f[j].u&&f[i].u<=f[j].u) return 1; return 0; } void dfs(int num){ val=0; for(int i=1;i<=k;i++){ if(f[i].falg) for(int j=i+1;j<=k;j++) if(f[j].falg&&judge(i,j)) return ; val+=(f[i].r-f[i].l)*(f[i].d-f[i].u);//统计到目前为止的矩形的面积和。 } if(val>=ans) return; if(num>n){ ans=val; return ; } for(int i=1;i<=k;i++){ none tmp=f[i]; if(!f[i].falg){ f[i].falg=1; f[i].l=f[i].r=v[num].x; f[i].d=f[i].u=v[num].y; dfs(num+1); f[i]=tmp; } else{ f[i].l=min(f[i].l,v[num].x); f[i].r=max(f[i].r,v[num].x); f[i].u=min(f[i].u,v[num].y); f[i].d=max(f[i].d,v[num].y); dfs(num+1); f[i]=tmp; } } } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d%d",&v[i].x,&v[i].y); dfs(1); cout<<ans; }