牛客多校第三场 D- Points Construction Problem
链接: Points Construction Problem
题意:
在2D平面内,每个格点(整数点)有一个白点,可以将其中一些点涂黑。
问能否将n个白点涂黑,使得有m对相邻的白点和黑点(指哈夫曼距离为1)
解法:
(1)若每个黑点都是不相邻的,则可以发现涂黑n个的黑白对数上限为4*n。
(2)如果每个黑点相邻,并排成一行,则此时黑白对数为2*n+2。
(3)可以发现黑白点对数一定是偶数,在(2)的基础上,将链上的黑点逐个拿出并放置在互不相邻处,则可以实现(2*n+2) 至 (4*n)所有偶数m的构造。
(4)如果m比(2*n+2)还要小,可以在(2)的基础上,将这条黑点链逐步卷曲来减少黑白点对数,每次减2,如下图:
代码:
#include <bits/stdc++.h>
using namespace std;
int vis[100][100];
int f(int u,int v){//周围黑点个数
return vis[u-1][v]+vis[u+1][v]+vis[u][v+1]+vis[u][v-1];
}
int main () {
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
if(n*4<m || m%2==1){
puts("No");
continue;
}
int srt=sqrt(n);
int rest=n-srt*srt;
int down=srt*4;
if(rest>0){
down+=2;
}
if(rest>srt){
down+=2;
}
if(m<down){
puts("No");
continue;
}
puts("Yes");
if((n*4-m)/2<n){//单链
int num2=(n*4-m)/2;
int num4=n-num2;
for(int i=1;i<=num2+1;i++){
printf("%d %d
",i,1);
}
num4--;
for(int i=1;i<=num4;i++){
printf("%d %d
",-i,-i);
}
}
else{//进行卷
memset(vis,0,sizeof vis);
int num0=(2*n+2-m)/2;
int cnt=0;
vis[50][50]=1;
cnt++;
printf("50 50
");
int x=50,y=50;
int turn=0;//0右,1上,2左,3下
for(int step=1;step<=10;step++){
for(int sstep=1;sstep<=2;sstep++){//同一步长走两次
if(turn==0){
for(int i=1;i<=step;i++){
x++;
vis[x][y]=1;
cnt++;
printf("%d %d
",x,y);
if(f(x,y)==2){
num0--;
}
if(num0==0 ||cnt==n){
break;
}
}
if(num0==0||cnt==n){
break;
}
turn=(turn+1)%4;
}
else if(turn==1){
for(int i=1;i<=step;i++){
y++;
vis[x][y]=1;
cnt++;
printf("%d %d
",x,y);
if(f(x,y)==2){
num0--;
}
if(num0==0 ||cnt==n){
break;
}
}
if(num0==0||cnt==n){
break;
}
turn=(turn+1)%4;
}
else if(turn==2){
for(int i=1;i<=step;i++){
x--;
vis[x][y]=1;
cnt++;
printf("%d %d
",x,y);
if(f(x,y)==2){
num0--;
}
if(num0==0 ||cnt==n){
break;
}
}
if(num0==0||cnt==n){
break;
}
turn=(turn+1)%4;
}
else if(turn==3){
for(int i=1;i<=step;i++){
y--;
vis[x][y]=1;
cnt++;
printf("%d %d
",x,y);
if(f(x,y)==2){
num0--;
}
if(num0==0 ||cnt==n){
break;
}
}
if(num0==0||cnt==n){
break;
}
turn=(turn+1)%4;
}
}
if(num0==0||cnt==n){
break;
}
}
if(cnt!=n){
if(turn==0){//右转下
while(cnt<n){
y--;
printf("%d %d
",x,y);
cnt++;
}
}
else if(turn==1){//上转右
while(cnt<n){
x++;
printf("%d %d
",x,y);
cnt++;
}
}
else if(turn==2){//左转上
while(cnt<n){
y++;
printf("%d %d
",x,y);
cnt++;
}
}
else if(turn==3){//下转左
while(cnt<n){
x--;
printf("%d %d
",x,y);
cnt++;
}
}
}
}
}
}