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;
}
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。