P1034 矩形覆盖

第一反应就是大法师:枚举横着切和竖着切。

感觉这样就已经对了,但后来想想貌似存在这样一种状况。

其实想想这种情况也不会是最优的。但是这题k等于四,总觉得不讨论一下就很不舒服。

然后就A掉了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define db double
#define mkp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define X first
#define Y second
const int N=51,M=500;
int n,k,ans;pii v[N];
bool cmp(pii x,pii y){
	return x.Y==y.Y?x.X<y.X:x.Y<y.Y;
}
int cal(int l,int r,int d,int u){
	return (r-l)*(u-d);
}
void f1(pii v1,pii v2){
	int h,u1=v1.Y,l1=v1.X,d2=v2.Y,r2=v2.X,u3=0,d3=M,l3=M,r3=0,u4=0,d4=M,l4=M,r4=0;
	rep(h,1,n)if(v[h]!=v1&&v[h]!=v2){
		if(v[h].X<=v1.X&&v[h].Y>=v1.Y)
			u1=max(u1,v[h].Y),l1=min(l1,v[h].X);
		if(v[h].X>=v2.X&&v[h].Y<=v2.Y)
			d2=min(d2,v[h].Y),r2=max(r2,v[h].X);
		if(v[h].X>v1.X&&v[h].Y>v2.Y)
			u3=max(u3,v[h].Y),d3=min(d3,v[h].Y),l3=min(l3,v[h].X),r3=max(r3,v[h].X);
		if(v[h].X<v2.X&&v[h].Y<v1.Y)
			u4=max(u4,v[h].Y),d4=min(d4,v[h].Y),l4=min(l4,v[h].X),r4=max(r4,v[h].X);
	}
	ans=min(ans,cal(l1,v1.X,v1.Y,u1)+cal(v2.X,r2,d2,v2.Y)+cal(l3,r3,d3,u3)+cal(l4,r4,d4,u4));
}
void f2(pii v1,pii v2){
	int h,u1=v1.Y,r1=v1.X,d2=v2.Y,l2=v2.X,u3=0,d3=M,l3=M,r3=0,u4=0,d4=M,l4=M,r4=0;
	rep(h,1,n)if(v[h]!=v1&&v[h]!=v2){
		if(v[h].X>=v1.X&&v[h].Y>=v1.Y)
			u1=max(u1,v[h].Y),r1=max(r1,v[h].X);
		if(v[h].X<=v2.X&&v[h].Y<=v2.Y)
			d2=min(d2,v[h].Y),l2=max(l2,v[h].X);
		if(v[h].X<v1.X&&v[h].Y>v2.Y)
			u3=max(u3,v[h].Y),d3=min(d3,v[h].Y),l3=min(l3,v[h].X),r3=max(r3,v[h].X);
		if(v[h].X>v2.X&&v[h].Y<v1.Y)
			u4=max(u4,v[h].Y),d4=min(d4,v[h].Y),l4=min(l4,v[h].X),r4=max(r4,v[h].X);
	}
	ans=min(ans,cal(v1.X,r1,v1.Y,u1)+cal(l2,v2.X,d2,v2.Y)+cal(l3,r3,d3,u3)+cal(l4,r4,d4,u4));
}
int F1(int le,int ri,int cur);
int F2(int le,int ri,int cur); 
int main(){
	int i,j,h,x,y;pii v1,v2;
	scanf("%d%d",&n,&k);
	rep(i,1,n){
		scanf("%d%d",&x,&y);
		v[i]=mkp(x,y);
	}
	sort(v+1,v+n+1);
	j=0;rep(i,1,n)if(v[i]!=v[j])v[++j]=v[i];n=j;
	if(k>=n){puts("0");return 0;}ans=M*M;
	if(k==4){
		per(i,n-1,1){
			rep(j,i+1,n){
				v1=v[i],v2=v[j];
				if(v1.X==v2.X)f1(v1,v2),f2(v1,v2);
				else if(v1.Y==v2.Y)f1(v1,v2),f2(v2,v1);
				else{
					x=min(v1.Y,v2.Y),y=max(v1.Y,v2.Y);
					rep(h,1,n)
						if(h!=i&&h!=j&&v[h].X>=v1.X&&v[h].X<=v2.X&&v[h].Y>=x&&v[h].Y<=y)
							break;
					if(h>n)
						if(v1.Y<v2.Y)f1(v2,v1),f1(v1,v2);
						else f2(v1,v2),f2(v2,v1);
				}
			}
		}
	}
	ans=min(ans,F1(1,n,k));
	printf("%d\n",ans);
	return 0;
}
int F1(int le,int ri,int cur){
	if(ri-le<cur)return 0;
	if(cur==1){
		int i,u=0,d=M,l=M,r=0;
		rep(i,le,ri)
			u=max(v[i].Y,u),d=min(v[i].Y,d),l=min(v[i].X,l),r=max(v[i].X,r);
		return cal(l,r,d,u);
	}
	int i,j,rtn=M*M;
	per(i,ri-1,le)
		per(j,cur-1,1)
			rtn=min(rtn,F1(le,i,j)+F1(i+1,ri,cur-j));
	sort(v+le,v+ri+1,cmp);
	per(i,ri-1,le)
		per(j,cur-1,1)
			rtn=min(rtn,F2(le,i,j)+F2(i+1,ri,cur-j));
	sort(v+le,v+ri+1);
	return rtn;
}
int F2(int le,int ri,int cur){
	if(ri-le<cur)return 0;
	if(cur==1){
		int i,u=0,d=M,l=M,r=0;
		rep(i,le,ri)
			u=max(v[i].Y,u),d=min(v[i].Y,d),l=min(v[i].X,l),r=max(v[i].X,r);
		return cal(l,r,d,u);
	}
	int i,j,rtn=M*M;
	per(i,ri-1,le)
		per(j,cur-1,1)
			rtn=min(rtn,F2(le,i,j)+F2(i+1,ri,cur-j));
	sort(v+le,v+ri+1);
	per(i,ri-1,le)
		per(j,cur-1,1)
			rtn=min(rtn,F2(le,i,j)+F2(i+1,ri,cur-j));
	sort(v+le,v+ri+1,cmp);
	return rtn;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值