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

题目描述

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

A_zjzj

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

输入格式

n k n k
x 1 y 1 x_1 y_1
x 2 y 2 x_2 y_2
. . . . . . ... ...
x n y n x_n y_n
( 0 x i , y i 500 0 \le x_i,y_i \le 500 )

输出格式

输出至屏幕。格式为:

1 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

发布了48 篇原创文章 · 获赞 49 · 访问量 2123

猜你喜欢

转载自blog.csdn.net/A_zjzj/article/details/104990756
今日推荐