1. 程式人生 > 實用技巧 >牛客多校第三場 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,如下圖:

程式碼:

#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++;
                    }
                }
            }
        }
    }
}