P1034 矩形覆盖(dfs,剪枝)

P1034 矩形覆盖

不想写题意描述了,看链接吧。。。

题目分析

由于数据范围较小 k &lt; 5 , n &lt; 50 k&lt;5,n&lt;50 k<5,n<50)所以考虑直接搜索,通过搜索来确定每个点是否能放进一个矩形中,状态记录当前点被矩形覆盖后的总面积.

程序实现

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
struct Node{
	int x,y;
}node[55];
struct square{
	int x1,y1,x3,y3;
}sqr[6];
int n,k,ans,tot,maxn=inf;
bool check(int now,int sq){//check函数用来检查该点放入该矩形是否合法
	if(sqr[sq].x1 ==0&&sqr[sq].y1 ==0&&sqr[sq].x3 ==0&&sqr[sq].y3 ==0){
		sqr[sq].x1 =sqr[sq].x3 =node[now].x ;
		sqr[sq].y1 =sqr[sq].y3 =node[now].y ;
	}//矩形赋初值
	if(node[now].x <sqr[sq].x1 ) sqr[sq].x1 =node[now].x ;
	if(node[now].y <sqr[sq].y1 ) sqr[sq].y1 =node[now].y ;
	if(node[now].x >sqr[sq].x3 ) sqr[sq].x3 =node[now].x ;
	if(node[now].y >sqr[sq].y3 ) sqr[sq].y3 =node[now].y ;//已有初值,矩形大小改变
	for(int i=1;i<=k;i++){
		if(i==sq)continue;
		if(sqr[sq].x1 <=sqr[i].x3 &&sqr[sq].y1 <=sqr[i].y3 &&sqr[i].x3 <=sqr[sq].x3 &&sqr[i].y3 <=sqr[sq].y3 )return false;
		if(sqr[sq].x1 <=sqr[i].x1 &&sqr[sq].y1 <=sqr[i].y1 &&sqr[i].x1 <=sqr[sq].x3 &&sqr[i].y1 <=sqr[sq].y3 )return false;
		if(sqr[sq].y1 <=sqr[i].y1 &&sqr[i].y1 <=sqr[sq].y3 &&sqr[sq].x1 <=sqr[i].x1 &&sqr[i].x1 <=sqr[sq].x3 )return false;
		if(sqr[sq].y1 <=sqr[i].y3 &&sqr[i].y3 <=sqr[sq].y3 &&sqr[sq].x1 <=sqr[i].x3 &&sqr[i].x3 <=sqr[sq].x3 )return false;//判断矩形重合(不包括点和边)
		if(sqr[sq].x1 ==sqr[i].x1 &&sqr[sq].y1 ==sqr[i].y1 )return false;
		if(sqr[sq].x3 ==sqr[i].x3 &&sqr[sq].y3 ==sqr[i].y3 )return false;
		if(sqr[sq].x3 ==sqr[i].x1 &&sqr[sq].y1 ==sqr[i].y3 )return false;
		if(sqr[sq].x1 ==sqr[i].x3 &&sqr[sq].y3 ==sqr[i].y1 )return false;//没写这个特判就只剩80了,判断边点重合
	}
	return true;//没有以上情况,可以放入该矩形
}
void dfs(int now){
	if(now>n&&tot<maxn){
		maxn=tot;//用maxn表示最小值,我是不是有点毛病……凑合看吧
		return ;
	}
	if(now>n||tot>=maxn)return ;//函数递归的三种情况:已超出n,还没到n矩形面积和就比当前最小面积和大了,或者是已经放不进任何一个矩形了
	for(int i=1;i<=k;i++){
		int a=sqr[i].x1 ,b=sqr[i].y1 ,c=sqr[i].x3 ,d=sqr[i].y3 ;
		if(check(now,i)){
			int sum=(sqr[i].x3 -sqr[i].x1 )*(sqr[i].y3 -sqr[i].y1 )-(c-a)*(d-b);
			tot+=sum;
			dfs(now+1);
			tot-=sum;
		}
		sqr[i].x1 =a,sqr[i].y1 =b,sqr[i].x3 =c,sqr[i].y3 =d;//记得开临时数存先前状态
	}
	return ;
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&node[i].x ,&node[i].y );
	}
	dfs(1);
	printf("%d\n",maxn);
	return 0;
} 

题后总结

又一次没有认真看题。。。题目说的“边线与顶点也都不能重合”被你吃了吗!?

zyb说的果然对,这种小数据范围的题就考虑爆搜,注意特判和剪枝.

u p d a t e update update

好像原先做法不是正解?正解发一波.

https://wenku.baidu.com/view/5f8961b47fd5360cba1adbeb.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值