AGC025D - Choosing Points 题解

题目大意:给定一个\(2n\times 2n\)的平面,在上面取\(n\times n\)个整点,使得任意两点之间距离\(\neq \sqrt{D1},\sqrt{D2}\)

题目链接:D - Choosing Points


题解:我们先考虑只有\(D1\)限制的情况,我们将所有距离为\(\sqrt{D1}\)的整点连上边,会发现这是一张二分图。证明如下:

考虑将棋盘黑白染色,如果\(D1\)为奇数,那么黑点和黑点之间不可能连边,白点和白点之间也不可能连边,所以容易证明。

如果\(D1\)为偶数,黑点之间会互相连边,白点亦是如此,那么将坐标缩小为原来的\(\frac{1}{\sqrt{2}}\),然后\(D1 \div 2\)转换为子问题。

所以按照\(D1\)的限制黑白染色,然后在按照\(D2\)的限制红蓝染色,根据染色结果将所有的分为 4 类,由于鸽巢原理,一定有至少一类的大小是大于\(n\times n\)的,所以直接输出即可。

代码:

#include <cstdio>
#include <cstring>
const int Maxn=600;
const int D[4][2]={{1,1},{1,-1},{-1,1},{-1,-1}};
int n,d[2];
int step[2][2][Maxn*Maxn+5];
int len[2];
int num[5];
int col[2][Maxn+5][Maxn+5];
void dfs(int k,int x,int y,int c){
	if(x<1||y<1||x>n||y>n||col[k][x][y]!=-1){
		return;
	}
	col[k][x][y]=c;
	for(int i=1;i<=len[k];i++){
		for(int j=0;j<4;j++){
			dfs(k,x+D[j][0]*step[k][0][i],y+D[j][1]*step[k][1][i],c^1);
		}
	}
}
int main(){
	scanf("%d%d%d",&n,&d[0],&d[1]);
	n<<=1;
	for(int k=0;k<2;k++){
		for(int i=0;i<=n;i++){
			for(int j=0;j<=n;j++){
				if(i*i+j*j==d[k]){
					step[k][0][++len[k]]=i;
					step[k][1][len[k]]=j;
				}
			}
		}
	}
	memset(col,-1,sizeof col);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			dfs(0,i,j,0);
			dfs(1,i,j,0);
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			num[col[1][i][j]<<1|col[0][i][j]]++;
		}
	}
	int tmp;
	for(int i=0;i<4;i++){
		if(num[i]>=(n*n>>2)){
			tmp=i;
		}
	}
	int sz=0;
	for(int i=1;i<=n&&(sz<(n*n>>2));i++){
		for(int j=1;j<=n&&(sz<(n*n>>2));j++){
			if((col[1][i][j]<<1|col[0][i][j])==tmp){
				sz++;
				printf("%d %d\n",i-1,j-1);
			}
		}
	}
	return 0;
}
posted @ 2020-07-23 15:36  with_hope  阅读(169)  评论(0编辑  收藏  举报