20200208 第三场
进度(2/10) 未完成:-
A、牛牛的DRB迷宫I
1、链接
https://ac.nowcoder.com/acm/contest/3004/A
2、题面
牛牛有一个n*m的迷宫,对于迷宫中的每个格子都为'R','D','B'三种类型之一,'R'表示处于当前的格子时只能往右边走'D'表示处于当前的格子时只能往下边走,而'B'表示向右向下均可以走。
我们认为迷宫最左上角的坐标为(1,1),迷宫右下角的坐标为(n,m),除了每个格子有向右移动以及向下移动的限制之外,你也不能够走出迷宫的边界。
牛牛现在想要知道从左上角走到右下角不同种类的走法共有多少种,请你告诉牛牛从(1,1)节点移动到(n,m)节点共有多少种不同的移动序列,请你输出方案数对10^9+7取余数后的结果。
我们认为两个移动序列是不同的,当且仅当移动序列的长度不同,或者在某一步中采取了不同的移动方式。
3、思路
DP。状态转移:f[i][j] = f[i][j - 1] (if a[i][j - 1] = 'R' / 'B') + f[i - 1][j] (if a[i - 1][j] = 'D' / 'B')。
4、代码
1 #include2 using namespace std; 3 4 #define MAXN 55 5 #define MOD 1000000007 6 7 int n, m; 8 char a[MAXN][MAXN]; 9 int f[MAXN][MAXN]; 10 11 int main() { 12 cin >> n >> m; 13 for (int i = 1; i <= n; i++) cin >> a[i] + 1; 14 f[1][1] = 1; 15 for (int i = 1; i <= n; i++) 16 for (int j = 1; j <= m; j++) { 17 if (i == j && j == 1) continue; 18 if (a[i][j - 1] == 'R' || a[i][j - 1] == 'B') (f[i][j] += f[i][j - 1]) %= MOD; 19 if (a[i - 1][j] == 'D' || a[i - 1][j] == 'B') (f[i][j] += f[i - 1][j]) %= MOD; 20 } 21 cout << f[n][m]; 22 return 0; 23 }
C、牛牛的数组越位
1、链接
https://ac.nowcoder.com/acm/contest/3004/C
2、题面
牛牛写了这样一个C/C++程序:
#includeusing namespace std; int main() { int a[5][5]; a[-1][8]=12345; printf("%d %d",a[1][-2],a[0][3]); return 0; }
他发现程序可以正常运行,并且输出为:
12345 12345
在C/C++中,这种数组越位行为是Undefined Behaviour(UB)的,也就是程序未定义行为,但是在牛牛的编译器呢,对于这种情况,二维数组的内存是连续的。
也就是说对于二维数组int a[5][5],在牛牛的电脑中是按照a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[1][0]...a[1][4],a[2][0]...a[2][4],a[3][0]...a[4][4]
这样储存的。
牛牛所使用的编译器在寻址时是这样处理的,对于一个二维数组a[n][m],若对a[x][y]这个数组元素进行操作,最终访问到的地址为:a的首地址+m*x+y。
所以在寻址时,无论是a[-1][8]还是a[1][-2]最终在牛牛的电脑上使用该编译器编译出的程序均未发生非法访问的行为,他们最终都表示a[0][3]这个数组元素。
本题有T组测试数据。
牛牛先声明了一个n*m的int型数组,即int a[n][m];,这个数组被他声明成一个全局变量,所以数组的初值全为0,接下来他要进行p次赋值运算。
每次他都选择一个二维下标x,y,并且把a[x][y]赋值成val。
当然,牛牛不会老老实实按照C语言的规范来写代码。
如果这p次赋值操作中不存在数组越位行为,则先输出n行,每行m个数。表示操作后的二维数组,数字之间用一个空格隔开,行末没有多余空格。然后输出一行"Accepted"(不含引号),表示正常运行。
如果这p次赋值操作中虽然存在数组越位行为但是没有发生非法访问,则先输出n行,每行m个数。表示操作后的二维数组,数字之间用一个空格隔开,行末没有多余空格。然后输出一行"Undefined Behaviour"(不含引号),表示虽然能够运行,但是牛牛的代码不规范存在隐患。
如果这p次赋值操作中出现了至少一次数组越位并且导致非法访问的行为,请输出一行一个字符串"Runtime error"(不含引号)。
3、思路
根据题意,a[x][y]可以化为a[(m * x + y) / m][(m * x + y) % m],再依次代入,判断是否出现越位以及非法访问的情况。
4、代码
1 #include2 using namespace std; 3 4 #define MAXN 1005 5 6 int n, m, t, p, x, y, v; 7 int a[MAXN][MAXN]; 8 9 int main() { 10 cin >> t; 11 for (int i = 1; i <= t; i++) { 12 int tp = 1; 13 memset(a, 0, sizeof(a)); 14 cin >> n >> m >> p; 15 for (int j = 1; j <= p; j++) { 16 cin >> x >> y >> v; 17 int o = m * x + y; 18 if (o >= n * m || o < 0) tp = 3; 19 else { 20 if (x < 0 || y < 0 || x >= n || y >= m) tp = 2; 21 a[o / m][o % m] = v; 22 } 23 } 24 if (tp == 3) cout << "Runtime error" << endl; 25 else { 26 for (int j = 0; j < n; j++) { 27 for (int k = 0; k < m; k++) cout << a[j][k] << ' '; 28 cout << endl; 29 } 30 cout << ((tp == 2) ? "Undefined Behaviour" : "Accepted") << endl; 31 } 32 } 33 return 0; 34 }