2020牛客寒假算法基础集训营3 【B】-牛牛的DRB迷宫II

题目链接:https://ac.nowcoder.com/acm/contest/3004/B

第一次写这种构造题,比赛的时候没想出来QAQ。构造方法很巧妙。先把官方题解的图拉过来。

解释一下这张图:初始状态如图,空白区域(除了最后一行)全填D,最后一行全填R。

从0开始计数,第i行第i列(即对角线元素)的值为2i(也就是1<<i)。2n之内的所有2的倍数通过各种组合的相加可以构成1到2n+1之间的所有数字。为便于理解对上图修改如下

要求res对应的方格为最终答案,只需要判定res是由哪些数字构成的和,然后将对应列的蓝色区域的R改为B即可。这样就会将当前列对应的值向下传递直到最后一行。

然后既然答案会对1e9+7取模,所以我们只需要计算30列,因为1<<30=1 073 741 824,下标0~29。

扫描二维码关注公众号,回复: 9042842 查看本文章

对于行数而言需要32行,因为第31行(下标30)需要对第30行(下标29)的数据进行选择是否处理。第32行(下标31)全R来将答案从左到右传递到最后一格。

对于判断由哪些数字组成的和利用二进制和位运算即可。

附代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=55;
 4 char res[maxn][maxn];
 5 int main(){
 6     int n=32,m=30;
 7     int k;
 8     cin>>k;
 9     for(int i=0;i<30;i++){
10         res[0][i]='D';
11         res[30][i]='D';
12         res[31][i]='R';
13     }
14     res[0][0]='B';
15     res[30][29]='R';
16     for(int i=1;i<30;i++){
17         for(int j=0;j<i-1;j++){
18             res[i][j]='D';
19         }
20         res[i][i-1]='R';
21         res[i][i]='B';
22         for(int j=i+1;j<30;j++){
23             res[i][j]='D';
24         }
25     }
26     for(int i=0;i<30;i++){
27         if(k&(1<<i))res[i+1][i]='B';
28     }
29     cout<<n<<" "<<m<<"\n";
30     for(int i=0;i<n;i++){
31         for(int j=0;j<m;j++){
32             cout<<res[i][j];
33         }
34         cout<<"\n";
35     }
36     return 0;
37 }

猜你喜欢

转载自www.cnblogs.com/charles1999/p/12288606.html