纪中模拟赛——棋盘覆盖

题目:

在一个2^k× 2^k个方格组成的棋盘中恰有一个方格与其他方格不同(图中标记为-1 的方格),称之为特殊方格。现用L 型(占3 个小格)纸片覆盖棋盘上除特殊方格的所有部分,各纸片不得重叠,于是,用到的纸片数恰好是(4^k−1) / 3 。在下表给出的一个覆盖方案中,k=2,相同的3个数字构成一个纸片。

输入

输入文件Chessboard.in,共两行,第一行一个数N为棋盘的大小,N满足条件N=2^K,1<=K<=10.
第二行,两个数x,y,表示棋盘中那一个与其它方格不同的位置,x表示行,y表示列.

输出

输出文件Chessboard.out,输出N行N列,共N×N个数,表示用L 型(占3 个小格)纸片覆盖棋盘上除特殊方格的所有部分,各纸片不得重叠的方法.其中的数表示L型纸片覆盖的顺序编号, 不同的L型纸片用不同的编号,同一个L型纸片占据的三个位置相同,编号从1开始,特殊方格用-1标志;每两个数之间用一个空格隔开,每行最末一个数后面没有空格.

样例输入

4
2 2

样例输出

2 2 3 3
2 -1 1 3
4 1 1 5
4 4 5 5

数据范围限制

【限制】
对于50%的数据, 2<= N<=128;
对于100%的数据, 2<= N<=1024;

前言:

敲码半小时,抠错三小时~欢迎来到棋盘覆盖专卖店

解题思路:

分治——不多说了 程序能告诉你一切 某大佬看着我写博客,说:“看了程序半点不懂”
然后,这位大佬提供给我两张图~在这里谢谢大佬~
———— → → 大佬博客 ← ← ————
红色是特殊方格,黄色是L型纸片
第一步
第二步

源程序:

#include <bits/stdc++.h>
using namespace std;
int n,x,y,a[1030][1030],v,s,u,ans;
void dg(int x,int y,int qx,int qy,int s)
{
    if(s==1) return;
    int t=ans++;
    s=s/2;
    if(qx>=x+s&&qy>=y+s)
     {
        a[x+s-1][y+s-1]=t;
        a[x+s-1][y+s]=t;
        a[x+s][y+s-1]=t; 
        dg(x,y,x+s-1,y+s-1,s);
        dg(x+s,y,x+s,y+s-1,s); 
        dg(x,y+s,x+s-1,y+s,s);
        dg(x+s,y+s,qx,qy,s);
     }
    if(qx>=x+s&&qy<y+s)
     {
        a[x+s-1][y+s-1]=t;
        a[x+s-1][y+s]=t;
        a[x+s][y+s]=t;
        dg(x,y,x+s-1,y+s-1,s);
        dg(x+s,y,qx,qy,s);
        dg(x,y+s,x+s-1,y+s,s);
        dg(x+s,y+s,x+s,y+s,s);
     }
    if(qx<x+s&&qy>=y+s)
     {
        a[x+s-1][y+s-1]=t;
        a[x+s][y+s-1]=t;
        a[x+s][y+s]=t;
        dg(x,y,x+s-1,y+s-1,s); 
        dg(x+s,y,x+s,y+s-1,s); 
        dg(x,y+s,qx,qy,s);
        dg(x+s,y+s,x+s,y+s,s);
     }
    if(qx<x+s&&qy<y+s)
     {
        a[x+s-1][y+s]=t;
        a[x+s][y+s-1]=t;
        a[x+s][y+s]=t;
        dg(x,y,qx,qy,s);
        dg(x+s,y,x+s,y+s-1,s);
        dg(x,y+s,x+s-1,y+s,s);
        dg(x+s,y+s,x+s,y+s,s);
     }
}
int main()
{
    freopen("chessboard.in","r",stdin);
    freopen("chessboard.out","w",stdout);
    scanf("%d",&n);
    scanf("%d%d",&x,&y);
    a[x][y]=-1;ans=1;
    dg(1,1,x,y,n);
    for (int i=1;i<=n;i++,printf("\n"))
        for(int j=1;j<=n;j++)
         if (j!=n) printf("%d ",a[i][j]);
         else printf("%d",a[i][j]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值