构造-牛客寒假集训营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,...。 ①、设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 = 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增加方案数。
对于输入的k不是2的幂的情况,可以通过最后一行的R增加方案数。
② 、 对 k 的 二 进 制 进 行 扫 描 , 若 k 的 二 进 制 形 式 第 i 位 是 1 , 那 么 就 把 上 图 中 的 第 i 列 主 对 角 线 以 下 的 R 全 部 用 D 覆 盖 。 ( 除 主 对 角 线 下 的 第 一 个 R 用 B 覆 盖 和 最 后 一 行 的 R 保 留 ) 。 ②、对k的二进制进行扫描,若k的二进制形式第i位是1,那么就把上图中的第i列主对角线以下的R全部用D覆盖。\\(除主对角线下的第一个R用B覆盖和最后一行的R保留)。 ②、对k的二进制进行扫描,若k的二进制形式第i位是1,那么就把上图中的第i列主对角线以下的R全部用D覆盖。(除主对角线下的第一个R用B覆盖和最后一行的R保留)。
接
着
按
照
②
做
相
应
的
修
改
(
橙
色
部
分
为
修
改
部
分
)
:
接着按照②做相应的修改(橙色部分为修改部分):
接着按照②做相应的修改(橙色部分为修改部分):
在
修
改
之
前
,
到
达
(
5
,
5
)
所
在
的
B
有
16
种
方
案
。
在修改之前,到达(5,5)所在的B有16种方案。
在修改之前,到达(5,5)所在的B有16种方案。
接 着 我 们 对 25 的 二 进 制 形 式 11001 进 行 扫 描 , 第 一 位 为 1 , 因 此 在 第 一 列 增 加 一 条 路 径 , 把 第 一 列 对 角 线 下 的 第 一 个 R 改 为 B ( 原 本 是 R , 为 了 增 加 路 线 , 需 要 既 可 以 往 右 走 , 也 可 以 向 下 走 ) , 除 最 后 一 行 外 , 其 余 改 为 D , 因 为 在 修 改 之 前 到 达 第 一 列 的 主 对 角 线 上 的 B 只 有 一 种 方 案 , 所 以 向 下 增 加 一 条 路 径 , 总 方 案 仅 增 加 一 条 。 接着我们对25的二进制形式11001进行扫描,\\第一位为1,因此在第一列增加一条路径,把第一列对角线下的第一个R改为B\\(原本是R,为了增加路线,需要既可以往右走,也可以向下走),除最后一行外,其余改为D,\\因为在修改之前到达第一列的主对角线上的B只有一种方案,所以向下增加一条路径,总方案仅增加一条。 接着我们对25的二进制形式11001进行扫描,第一位为1,因此在第一列增加一条路径,把第一列对角线下的第一个R改为B(原本是R,为了增加路线,需要既可以往右走,也可以向下走),除最后一行外,其余改为D,因为在修改之前到达第一列的主对角线上的B只有一种方案,所以向下增加一条路径,总方案仅增加一条。
继 续 扫 描 , 第 4 位 为 1 , 因 此 将 第 四 列 的 主 对 角 线 以 下 的 第 一 个 R 更 改 为 B , 除 最 后 一 行 外 , 其 余 改 为 D 。 因 为 在 修 改 之 前 到 达 第 四 列 主 对 角 线 上 的 B 共 有 8 种 方 案 , 所 以 向 下 增 加 一 条 路 径 , 总 方 案 增 加 8 种 方 案 。 继续扫描,第4位为1,因此将第四列的主对角线以下的第一个R更改为B,除最后一行外,其余改为D。\\因为在修改之前到达第四列主对角线上的B共有8种方案,所以向下增加一条路径,总方案增加8种方案。 继续扫描,第4位为1,因此将第四列的主对角线以下的第一个R更改为B,除最后一行外,其余改为D。因为在修改之前到达第四列主对角线上的B共有8种方案,所以向下增加一条路径,总方案增加8种方案。
最 后 , 到 达 ( 6 , 6 ) 所 在 的 R 共 有 16 + 1 + 8 = 25 种 方 案 。 最后,到达(6,6)所在的R共有16+1+8=25种方案。 最后,到达(6,6)所在的R共有16+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],小于230,所以矩阵最大应该是31×31(要多一行一列全放R,最后一行用于增加路径)。
另 外 : 注 意 特 判 k = 0 的 时 候 不 能 是 1 × 1 的 矩 阵 。 另外:注意特判k=0的时候不能是1×1的矩阵。 另外:注意特判k=0的时候不能是1×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;
}