洛谷P1034矩形覆盖题解--zhengjun

题目描述

在平面上有 \(n\) 个点(\(n \le 50\)),每个点用一对整数坐标表示。例如:当 \(n=4\) 时,\(4\) 个点的坐标分另为:\(p_1\)(\(1,1\)),\(p_2\)(\(2,2\)),\(p_3\)(\(3,6\)),\(p_4\)(\(0,7\)),见图一。

A_zjzj

这些点可以用 \(k\) 个矩形(\(1 \le k \le 4\))全部覆盖,矩形的边平行于坐标轴。当 \(k=2\) 时,可用如图二的两个矩形 \(s_1,s_2\) 覆盖,\(s_1,s_2\) 面积和为 \(4\)。问题是当 \(n\) 个点坐标和 \(k\) 给出后,怎样才能使得覆盖所有点的 \(k\) 个矩形的面积之和为最小呢?
约定:覆盖一个点的矩形面积为 \(0\);覆盖平行于坐标轴直线上点的矩形面积也为 \(0\)。各个矩形必须完全分开(边线与顶点也都不能重合)。

输入格式

\(n k\)
\(x_1 y_1\)
\(x_2 y_2\)
\(... ...\)
\(x_n y_n\)
(\(0 \le x_i,y_i \le 500\))

输出格式

输出至屏幕。格式为:

\(1\) 个整数,即满足条件的最小的矩形面积之和。

输入输出样例

输入 #1 复制
4 2
1 1
2 2
3 6
0 7
输出 #1 复制
4

思路

这么一道数据小的题目如果不用搜索真是对不起这数据

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0x3fffffff,t;
struct zj1{
	int x,y;
};
zj1 f[51];
struct zj2{
	int a,b,c,d;
};
zj2 k[5];
bool check(int x){
	for(int i=1;i<=t;i++){
		if(i==x)continue;
		if(k[i].a<=k[x].a&&k[i].a>=k[x].b&&k[i].c>=k[x].c&&k[i].c<=k[x].d)return 0;
		if(k[i].a<=k[x].a&&k[i].a>=k[x].b&&k[i].d>=k[x].c&&k[i].d<=k[x].d)return 0;
		if(k[i].b<=k[x].a&&k[i].b>=k[x].b&&k[i].c>=k[x].c&&k[i].c<=k[x].d)return 0;
		if(k[i].b<=k[x].a&&k[i].b>=k[x].b&&k[i].d>=k[x].c&&k[i].d<=k[x].d)return 0;
	}
	return 1;
}
void dfs(int x){
	int sum=0;
	for(int i=1;i<=t;i++)
		sum+=(k[i].a-k[i].b)*(k[i].d-k[i].c);
	if(x>n){
		ans=min(ans,sum);
		return;
	}
	if(sum>=ans)
	    return;
	for(int j=1;j<=t;j++){
		int a=k[j].a,b=k[j].b,c=k[j].c,d=k[j].d;
		k[j].a=max(f[x].x,k[j].a);
		k[j].b=min(f[x].x,k[j].b);
		k[j].c=min(f[x].y,k[j].c);
		k[j].d=max(f[x].y,k[j].d);
		if(check(j))
			dfs(x+1);
		k[j].a=a;
		k[j].b=b;
		k[j].c=c;
		k[j].d=d;
	}
	if(t<m){
		t++;
		k[t].b=f[x].x;
		k[t].a=f[x].x;
		k[t].c=f[x].y;
		k[t].d=f[x].y;
		dfs(x+1);
		t--;
	}
	return;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&f[i].x,&f[i].y);
	dfs(1);
	cout<<ans;
	return 0;
}

谢谢--zhengjun

posted @ 2022-06-10 19:07  A_zjzj  阅读(72)  评论(0编辑  收藏  举报