其他分享
首页 > 其他分享> > 牛客多校第三场 D- Points Construction Problem(构造)

牛客多校第三场 D- Points Construction Problem(构造)

作者:互联网

牛客多校第三场 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,如下图:

1595234997186

代码:

#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\n",i,1);
            }
            num4--;
            for(int i=1;i<=num4;i++){
                printf("%d %d\n",-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\n");
            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\n",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\n",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\n",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\n",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\n",x,y);
                        cnt++;
                    }
                }
                else if(turn==1){//上转右
                    while(cnt<n){
                        x++;
                        printf("%d %d\n",x,y);
                        cnt++;
                    }
                }
                else if(turn==2){//左转上
                    while(cnt<n){
                        y++;
                        printf("%d %d\n",x,y);
                        cnt++;
                    }
                }
                else if(turn==3){//下转左
                    while(cnt<n){
                        x--;
                        printf("%d %d\n",x,y);
                        cnt++;
                    }
                }
            }
        }
    }
}

标签:vis,int,Points,多校,牛客,Construction,对数,黑点,第三场
来源: https://www.cnblogs.com/ucprer/p/13346013.html