题目:
《挑战程序设计竞赛》---坐标离散化,个人解法与看法Input
第一行输入w,h,n
第二行是i条线的一个起点的xi值
第三行是i条线的一个起点的yi值
第四行是i条线的另一个起点的xi值
第五行是i条线的另一个起点的yi值
Output
输出分割成多少个区域
Sample Input
10 10 5
1 1 4 9 10
6 10 4 9 10
4 8 1 1 6
4 8 10 5 10
Sample Output
6

解法

将前后没有变化的行列消除后并不会影响区域的个数。数组里只需要储存有直线的行列以及其前后的行列就足够了,这样的话最多6n*6n就足够了。

书上的原话

题目给出了所有线的首尾坐标,对于离散化,我们需要将行列分开操作。在操作列的时候不去管行的事情,将所有点的横坐标以及相邻的格子放入一个vector里面,排序,去重(相邻格子会重复),然后利用这个vector调整回原来的数组,行也是如此,这样就能离散化好了。
假如使用dfs的话极限条件下需要500乘500个栈。
另外我觉得将n条线都打横来放最多也就5003,为啥需要5006呢(书这么说我就这么敲了)

#include<bits/stdc++.h>
using namespace std;
const int maxn=500+5;
struct node{ // 假如做过《挑战程序设计竞赛》的超大背包问题的人 会发现 
	int x,y;	//那一题用的就是pair,但我在写的时候发现pair在排序的时候并不按照pair.first  
};			//那一题我用pair会错,后来还是自己写了一个结构体二分查找,所以这一题我依然不用pair(debug的阴影) 
int x1[maxn],x2[maxn],y1[maxn],y2[maxn];
int w,h,n; //宽 高 几条线 
int m[maxn*6][maxn*6]; 
int lat_w,lat_h; // 离散化后的宽和高 
int dir[4][2]={{0,1},{-1,0},{1,0},{0,-1}};
int lisan(int *a,int *b,int flag){  
	vector<int> sto; //协助离散化 将长/宽 用vector代替 
	for(int i=1;i<=n;i++){
		for(int j=-1;j<=1;j++){ //将只储存直线及其前后行列 
			int aa=a[i]+j,bb=b[i]+j;
			if(aa>=1&&aa<=flag) sto.push_back(aa);
			if(bb>=1&&bb<=flag) sto.push_back(bb);
		}
	}
	sort(sto.begin(),sto.end()); //这里是去重 
	sto.erase(unique(sto.begin(),sto.end()),sto.end());
	for(int i=0;i<n;i++){ //离散化 
		a[i+1]=find(sto.begin(),sto.end(),a[i+1])-sto.begin()+1; //我的地图从1开始 
		b[i+1]=find(sto.begin(),sto.end(),b[i+1])-sto.begin()+1;
	} //这里疯狂debug 
	return sto.size(); //返回压缩后的图的长/宽 
}
void bfs(int a,int b){//常规bfs 
	queue<node> Q;
	Q.push(node{a,b});
	m[a][b]=1;
	while(!Q.empty()){
		node N=Q.front(); Q.pop();
		for(int i=0;i<4;i++){
			int aa=N.x+dir[i][0],bb=N.y+dir[i][1];
			if(aa<1||aa>lat_w||bb<1||bb>lat_h) continue;
			if(!m[aa][bb]){
				m[aa][bb]=1;
				Q.push(node{aa,bb});
			}
		}
	}
}
int main(){
	cin>>w>>h>>n;
	for(int i=1;i<=n;i++) scanf("%d",&x1[i]);
	for(int i=1;i<=n;i++) scanf("%d",&x2[i]);
	for(int i=1;i<=n;i++) scanf("%d",&y1[i]);
	for(int i=1;i<=n;i++) scanf("%d",&y2[i]);
	lat_w=lisan(x1,x2,w);
	lat_h=lisan(y1,y2,h);
	memset(m,0,sizeof(m));
	for(int i=1;i<=n;i++){ // 开始构图 
		for(int j=x1[i];j<=x2[i];j++){
			for(int k=y1[i];k<=y2[i];k++){
				m[k][j]=1;
			}
		}
	} 
	int res=0;
	for(int i=1;i<=lat_h;i++){
		for(int j=1;j<=lat_w;j++){
			if(!m[i][j]){
				res++;
				bfs(i,j);
			}
		}
	}	
	cout<<res<<endl;
	return 0;
} 

由于没有题目,也只是过了书上的sample,可能会有错2333.

相关文章: