hdu多校赛第八场1009

题库6665传递门
题意,在坐标轴上给出两个矩形的坐标,判断两个矩形能将无限的空间分成几部分
两种做法:
一、直接用给的坐标判断两个矩形的关系(相交还是分离还是重叠),直接写的话要写很多个if,很麻烦所以建议食用第二种解法;第一种解法可以点传送门
二、将坐标离散化,用dfs求连通块:
离散化这里借鉴焦队的博客传送门

此处分别对x和y坐标进行离散化处理

for(int i = 1;i <= 4;i++){
	scanf("%d%d",&x[i],&y[i]);
	a[i] = x[i];
	b[i] = y[i];
}
sort(a+1,a+5);
sort(b+1,b+5);
int la = unique(a+1,a+5) - a - 1;
int lb = unique(b+1,b+5) - b - 1;
for(int i = 1;i <= 4;i++){
	x[i] = lower_bound(a+1,a+5,x[i]) - a;
	y[i] = lower_bound(b+1,b+5,y[i]) - b;
}

为了以防离散化坐标后,原本不重叠的坐标变重叠,这里将坐标乘二,防止出现错误(具体什么原因我也不知道,我是看别人博客的嘿嘿)

for(int i = 1;i <= 4;i++){
	x[i] *= 2;
	y[i] *= 2;
}

离散化完坐标后,将矩形构图,然后直接用dfs判断有多少连通块就可以了
直接给出AC代码

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
int x[5],y[5];
int a[5],b[5];//离散化辅助数组 
int aa[10][10],vis[10][10];
int xx[4] = {1,0,-1,0};
int yy[4] = {0,1,0,-1};

void dfs(int c,int d,int flag){
	for(int i = 0;i < 4;i++){
		int x_x = c + xx[i];
		int y_y = d + yy[i];
		if(x_x >= 0 && x_x <= 9 && y_y >= 0 && y_y <= 9 && aa[x_x][y_y] == 0 && vis[x_x][y_y] == 0){
			vis[x_x][y_y] = flag;
			dfs(x_x,y_y,flag);
		}
	}
}

int main(){
	int t;
	while(~scanf("%d",&t)){
		while(t--){
			for(int i = 1;i <= 4;i++){
				scanf("%d%d",&x[i],&y[i]);
				a[i] = x[i];
				b[i] = y[i];
			}
			sort(a+1,a+5);
			sort(b+1,b+5);
			int la = unique(a+1,a+5) - a - 1;
			int lb = unique(b+1,b+5) - b - 1;
			for(int i = 1;i <= 4;i++){
				x[i] = lower_bound(a+1,a+5,x[i]) - a;
				y[i] = lower_bound(b+1,b+5,y[i]) - b;
			}
			for(int i = 1;i <= 4;i++){
				x[i] *= 2;
				y[i] *= 2;
			}//乘2防止离散化后重叠
			//构图
			mem(vis,0);
			mem(aa,0); 
			for(int i=x[1]; i<=x[2]; i++)
	        {
	            aa[i][y[1]]=1,aa[i][y[2]]=1;
	        }
	        for(int i=y[1]; i<=y[2]; i++)
	        {
	            aa[x[1]][i]=1,aa[x[2]][i]=1;
	        }
	        for(int i=x[3]; i<=x[4]; i++)
	        {
	            aa[i][y[3]]=1,aa[i][y[4]]=1;
	        }
	        for(int i=y[3]; i<=y[4]; i++)
	        {
	            aa[x[3]][i]=1,aa[x[4]][i]=1;
	        }
	        int ans=0;
	        int flag=1;
	        for(int i=0; i<=9; i++)
	        {
	            for(int j=0; j<=9; j++)
	            {
	                if(aa[i][j]==0&&vis[i][j]==0)
	                {
	                    vis[i][j]=flag;
	                    dfs(i,j,flag);
	                    flag++;
	                }
	            }
	        }
	        printf("%d\n",flag-1);
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值