构造-牛客寒假集训营3-牛牛的DRB迷宫II

构造-牛客寒假集训营3-牛牛的DRB迷宫II

题目:
在这里插入图片描述
题意:

输 入 一 个 数 字 , 表 示 从 起 点 ( 1 , 1 ) 到 终 点 ( n , m ) 的 方 案 数 量 , 输 出 满 足 条 件 的 迷 宫 。 输入一个数字,表示从起点(1,1)到终点(n,m)的方案数量,输出满足条件的迷宫。 (1,1)(n,m)

是 迷 宫 问 题 的 强 化 版 — — 是迷宫问题的强化版—— 牛牛的DRB迷宫I

题解:

一 道 比 较 神 奇 的 构 造 , 比 较 难 想 。 一道比较神奇的构造,比较难想。

出题人的图

看了很多题解终于明白了出题人的题解(菜

① 、 设 k 的 二 进 制 最 高 位 1 所 在 的 位 数 是 m , 首 先 构 造 一 个 m × m 的 矩 阵 , 主 对 角 线 放 B , B 的 左 边 是 R , 右 边 是 D , 剩 下 的 所 有 空 都 放 R , 接 着 给 上 述 m × m 的 矩 阵 的 增 加 一 行 一 列 的 ′ R ′ 变 成 ( m + 1 ) × ( m + 1 ) 的 矩 阵 。 这 样 的 话 从 起 点 ( 1 , 1 ) 到 主 对 角 线 上 B 处 的 方 案 数 可 以 构 造 出 2 的 任 意 幂 次 1 , 2 , 4 , . . . 。 ①、设k的二进制最高位1所在的位数是m,首先构造一个m×m的矩阵,\\主对角线放B,B的左边是R,右边是D,剩下的所有空都放R,\\接着给上述m×m的矩阵的增加一行一列的'R'变成(m+1)×(m+1)的矩阵。\\这样的话从起点(1,1)到主对角线上B处的方案数可以构造出2的任意幂次1,2,4,...。 k1mm×m线BBRDRm×mR(m+1)×(m+1)(1,1)线B21,2,4,...

举 个 列 子 : k = 25 , k = 11001 , 则 m = 5 举个列子:k=25,k=11001,则m=5 k=25,k=11001,m=5

首 先 按 照 ① , 先 对 矩 阵 进 行 初 始 化 , 得 到 6 × 6 的 矩 阵 如 下 : 首先按照①,先对矩阵进行初始化,得到6×6的矩阵如下: 6×6
在这里插入图片描述
对 于 输 入 的 k 不 是 2 的 幂 的 情 况 , 可 以 通 过 最 后 一 行 的 R 增 加 方 案 数 。 对于输入的k不是2的幂的情况,可以通过最后一行的R增加方案数。 k2R

② 、 对 k 的 二 进 制 进 行 扫 描 , 若 k 的 二 进 制 形 式 第 i 位 是 1 , 那 么 就 把 上 图 中 的 第 i 列 主 对 角 线 以 下 的 R 全 部 用 D 覆 盖 。 ( 除 主 对 角 线 下 的 第 一 个 R 用 B 覆 盖 和 最 后 一 行 的 R 保 留 ) 。 ②、对k的二进制进行扫描,若k的二进制形式第i位是1,那么就把上图中的第i列主对角线以下的R全部用D覆盖。\\(除主对角线下的第一个R用B覆盖和最后一行的R保留)。 kki1i线RD(线RBR)

接 着 按 照 ② 做 相 应 的 修 改 ( 橙 色 部 分 为 修 改 部 分 ) : 接着按照②做相应的修改(橙色部分为修改部分): ()
在这里插入图片描述
在 修 改 之 前 , 到 达 ( 5 , 5 ) 所 在 的 B 有 16 种 方 案 。 在修改之前,到达(5,5)所在的B有16种方案。 (5,5)B16

接 着 我 们 对 25 的 二 进 制 形 式 11001 进 行 扫 描 , 第 一 位 为 1 , 因 此 在 第 一 列 增 加 一 条 路 径 , 把 第 一 列 对 角 线 下 的 第 一 个 R 改 为 B ( 原 本 是 R , 为 了 增 加 路 线 , 需 要 既 可 以 往 右 走 , 也 可 以 向 下 走 ) , 除 最 后 一 行 外 , 其 余 改 为 D , 因 为 在 修 改 之 前 到 达 第 一 列 的 主 对 角 线 上 的 B 只 有 一 种 方 案 , 所 以 向 下 增 加 一 条 路 径 , 总 方 案 仅 增 加 一 条 。 接着我们对25的二进制形式11001进行扫描,\\第一位为1,因此在第一列增加一条路径,把第一列对角线下的第一个R改为B\\(原本是R,为了增加路线,需要既可以往右走,也可以向下走),除最后一行外,其余改为D,\\因为在修改之前到达第一列的主对角线上的B只有一种方案,所以向下增加一条路径,总方案仅增加一条。 25110011线RB(R,线,,)D,线B

继 续 扫 描 , 第 4 位 为 1 , 因 此 将 第 四 列 的 主 对 角 线 以 下 的 第 一 个 R 更 改 为 B , 除 最 后 一 行 外 , 其 余 改 为 D 。 因 为 在 修 改 之 前 到 达 第 四 列 主 对 角 线 上 的 B 共 有 8 种 方 案 , 所 以 向 下 增 加 一 条 路 径 , 总 方 案 增 加 8 种 方 案 。 继续扫描,第4位为1,因此将第四列的主对角线以下的第一个R更改为B,除最后一行外,其余改为D。\\因为在修改之前到达第四列主对角线上的B共有8种方案,所以向下增加一条路径,总方案增加8种方案。 41线RBD线B88

最 后 , 到 达 ( 6 , 6 ) 所 在 的 R 共 有 16 + 1 + 8 = 25 种 方 案 。 最后,到达(6,6)所在的R共有16+1+8=25种方案。 (6,6)R16+1+8=25

因 为 二 进 制 形 式 下 可 以 表 示 任 意 一 个 整 数 , 因 此 无 论 如 何 都 可 以 找 出 满 足 条 件 的 迷 宫 矩 阵 。 因为二进制形式下可以表示任意一个整数,因此无论如何都可以找出满足条件的迷宫矩阵。

因 为 k ∈ [ 0 , 1 0 9 + 6 ] , 小 于 2 30 , 所 以 矩 阵 最 大 应 该 是 31 × 31 ( 要 多 一 行 一 列 全 放 R , 最 后 一 行 用 于 增 加 路 径 ) 。 因为k∈[0,10^9+6],小于2^{30},所以矩阵最大应该是31×31(要多一行一列全放R,最后一行用于增加路径)。 k[0,109+6],23031×31(R)

另 外 : 注 意 特 判 k = 0 的 时 候 不 能 是 1 × 1 的 矩 阵 。 另外:注意特判k=0的时候不能是1×1的矩阵。 k=01×1

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x7fffffff
using namespace std;
const int mod=1e9+7;
ll k;
int n;//最终矩阵的规模
char mp[55][55];
int main()
{
    scanf("%lld",&k);
    k%=mod;
    if(!k) {cout<<2<<" "<<2<<endl<<"RR\nRR\n";return 0;}//特判(一开始忘记输出2 2一直卡在%95...

    for(int i=0;i<=31;i++)
        if(k&((ll)1<<i))//计算出二进制形式下'1'所在的位数
            n=i+1;

    memset(mp,'R',sizeof(mp));
    for(int i=0;i<n;i++)//初始化矩阵
    {
        mp[i][i]='B';
        if(i+1<n) mp[i][i+1]='D';
    }

    for(int i=0;i<n;i++)
    {
        if(k&((ll)1<<i))//对矩阵进行模拟修改
        {
            for(int j=0;j+i<n-1;j++)
            {
                mp[j+i+1][i]='D';
                if(j==0) mp[j+i+1][i]='B';
            }
        }
    }

    cout<<n+1<<" "<<n+1<<endl;
    for(int i=0;i<=n;i++)
    {
        for(int j=0;j<=n;j++)
            printf("%c",mp[i][j]);
        puts("");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值