[COCI2017-2018#5] Spirale

ゝ一纸荒年。 2021-10-29 23:24 224阅读 0赞

前言

祭手博客第二篇~~~

话说这道题是真的冤屈: R E RE RE,将空间从 55 55 55改到 100 100 100就 A A A了 QwQ

为什么这 20 20 20分不能加上去哇哇哇哇哇!!QAQ

题目

题目描述

S t j e p a n Stjepan Stjepan经常和他的朋友们一起在 Z a g r e b Zagreb Zagreb的一家酒吧玩。然而, S t j e p a n Stjepan Stjepan有时会喝过多的苏打水,里面的糖会让他头晕,比如昨晚就是一个例子。而当他头晕时,脑海中始终会拥有相同的场景,这个场景是一些数字螺旋的涂鸦,但他不能完全记住这些图像的样子,但可以描述它们。

S t j e p a n Stjepan Stjepan回忆说,这个图形是一个表格,由 N N N行 M M M列的数字组成。此外,这个表格中还有 K K K个螺旋线,每个螺旋线的起点是已知的,以及它的移动方向,可以是顺时针或逆时针。螺旋通过以下方式进行:

1、最初,表格是空的,每个螺旋都在自己的初始位置。

2、随后的每一步,每个螺旋都会移动到自己的下一个位置。如果这个螺旋会离开表格边界,但也会在后面返回。

3、在完成 1 0 100 10^{100} 10100个步骤后,对于每个表格中的数字,是其中一个螺旋到达这个表格最早的位置。

顺逆如图: 1逆2顺
在这里插入图片描述

输入格式

第一行输入三个数字 N N N( 1 ≤ N ≤ 50 1≤N≤50 1≤N≤50), M M M( 1 ≤ M ≤ 50 1≤M≤50 1≤M≤50), K K K( 1 ≤ K ≤ N ∗ M 1≤K≤N*M 1≤K≤N∗M)

接下来 K K K行,每行输入 3 3 3个数字,前两个数字表示螺旋的起始坐标(表格左上角坐标为( 1 , 1 1,1 1,1)),第三个数字表示螺旋的旋转方向,如果第三个数字是 0 0 0,表示是顺时针旋转,如果是1,表示是逆时针旋转。

输出格式

输出这个 N N N行 M M M列的表格中经过螺旋的答案。题目保证螺旋的步骤不会超过 1 0 100 10^{100} 10100

样例

样例输入1

  1. 3 3 1
  2. 2 2 0

样例输出1

  1. 9 2 3
  2. 8 1 4
  3. 7 6 5

样例输入2

  1. 3 3 1
  2. 2 2 1

样例输出2

  1. 3 2 9
  2. 4 1 8
  3. 5 6 7

样例输入3

  1. 3 3 2
  2. 1 1 0
  3. 1 2 0

样例输出3

  1. 1 1 4
  2. 6 5 5
  3. 19 18 17

解析

这道题开始一看到 1 0 100 10^{100} 10100着实吓了一跳,而且这个螺旋可以旋到外面去,这确实虚得很。。。

因此就开始推情况,将 3 ∗ 3 3*3 3∗3的图顺时针逆时针都推了一下,一开始就成功得出了一个结论,这个螺旋线不可能超过 4 ∗ n ∗ n 4*n*n 4∗n∗n个。当然我不知道这对不对,因为推着推着就发现,其实这个螺旋线的边长最多即为它的出发点离这个矩阵的距离*2+1。

也就是说如图:
在这里插入图片描述
在这个图中,螺旋线的起点是这个阴影点,那么如果要让它笼罩整个矩阵的话,肯定它的一半的边长是这么大:
在这里插入图片描述
在这个图上,这个螺旋线最坏的情况跑成的矩阵如图所示,即它的边长的一半就是这个点离四条边的最长距离,然后再加上这个点,总共边长即为 d i s ∗ 2 + 1 dis*2+1 dis∗2+1

这么推完后这个题的难点基本就没了,剩下的就是简单的二维数组基本操作了,当然要注意的是控制下标的变量不能越界,不然也会 R E RE RE

参考代码

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <set>
  7. #include <map>
  8. #include <string>
  9. #include <queue>
  10. #include <stack>
  11. #include <cstring>
  12. #include <iostream>
  13. using namespace std;
  14. #define reg register
  15. #define LL long long
  16. #define INF 0x3f3f3f3f
  17. template<typename T>
  18. void re (T &x){
  19. x = 0;
  20. int f = 1;
  21. char c = getchar ();
  22. while (c < '0' || c > '9'){
  23. if (c == '-') f = -1;
  24. c = getchar ();
  25. }
  26. while (c >= '0' && c <= '9'){
  27. x = (x << 1) + (x << 3) + c - 48;
  28. c = getchar ();
  29. }
  30. x *= f;
  31. }
  32. template<typename T>
  33. void pr (T x){
  34. if (x < 0){
  35. putchar ('-');
  36. x = ~x + 1;
  37. }
  38. if (x / 10) pr (x / 10);
  39. putchar (x % 10 + 48);
  40. }
  41. int n, m, k, a[100][100];
  42. int main (){
  43. re (n); re (m); re (k);
  44. memset (a, INF, sizeof (a));
  45. while (k --){
  46. int xx, yy, ty, num, tot = 0, cnt = 1;
  47. re (xx); re (yy); re (ty);
  48. a[xx][yy] = min (a[xx][yy], num = 1);
  49. tot = max (tot, n - xx);
  50. tot = max (tot, m - yy);
  51. tot = max (tot, xx - 1);
  52. tot = max (tot, yy - 1);
  53. tot = (tot * 2 + 1) * (tot * 2 + 1);
  54. //if (xx - 1 > 0) a[xx - 1][yy] = min (a[xx - 1][yy], num = 2);
  55. if (ty == 1){
  56. int x = xx, y = yy;
  57. int flag = 0;
  58. while (num < tot){
  59. int tmp = 1; flag ++;
  60. if (flag & 1) cnt ++;
  61. while (tmp < cnt && num < tot){
  62. tmp ++; num ++; x --;
  63. if (x > 0 && y > 0 && y <= m) a[x][y] = min (a[x][y], num);
  64. }
  65. tmp = 1; flag ++;
  66. if (flag & 1) cnt ++;
  67. while (tmp < cnt && num < tot){
  68. tmp ++; num ++; y --;
  69. if (x > 0 && y > 0 && x <= n) a[x][y] = min (a[x][y], num);
  70. }
  71. tmp = 1; flag ++;
  72. if (flag & 1) cnt ++;
  73. while (tmp < cnt && num < tot){
  74. tmp ++; num ++; x ++;
  75. if (x <= n && x > 0 && y > 0 && y <= m) a[x][y] = min (a[x][y], num);
  76. }
  77. tmp = 1; flag ++;
  78. if (flag & 1) cnt ++;
  79. while (tmp < cnt && num < tot){
  80. tmp ++; num ++; y ++;
  81. if (x > 0 && y > 0 && y <= m && x <= n) a[x][y] = min (a[x][y], num);
  82. }
  83. }
  84. }
  85. else{
  86. int x = xx, y = yy;
  87. int flag = 0;
  88. while (num < tot){
  89. int tmp = 1; flag ++;
  90. if (flag & 1) cnt ++;
  91. while (tmp < cnt && num < tot){
  92. tmp ++; num ++; x --;
  93. if (x > 0 && y > 0) a[x][y] = min (a[x][y], num);
  94. }
  95. tmp = 1; flag ++;
  96. if (flag & 1) cnt ++;
  97. while (tmp < cnt && num < tot){
  98. tmp ++; num ++; y ++;
  99. if (x > 0 && y > 0 && y <= m) a[x][y] = min (a[x][y], num);
  100. }
  101. tmp = 1; flag ++;
  102. if (flag & 1) cnt ++;
  103. while (tmp < cnt && num < tot){
  104. tmp ++; num ++; x ++;
  105. if (x > 0 && y > 0 && x <= n) a[x][y] = min (a[x][y], num);
  106. }
  107. tmp = 1; flag ++;
  108. if (flag & 1) cnt ++;
  109. while (tmp < cnt && num < tot){
  110. tmp ++; num ++; y --;
  111. if (x > 0 && y > 0) a[x][y] = min (a[x][y], num);
  112. }
  113. }
  114. }
  115. }
  116. for (int i = 1; i <= n; i++){
  117. for (int j = 1; j <= m; j++){
  118. pr (a[i][j]);
  119. putchar (' ');
  120. }
  121. putchar (10);
  122. }
  123. return 0;
  124. }

话说为什么听他们说好像直接大模拟也能过??不知道怎么搞的。。。

毕竟我不知道怎么判断整个矩阵到底填充完没有。。。而且就算填充完了也不一定是最小的,如果说直接模拟 2 100 2^{100} 2100那也太恐怖了吧, L L LL LL都没这么大、、、

果然我就是个蒟蒻 身边全是苣佬内心很受伤啊QwQ

发表评论

表情:
评论列表 (有 0 条评论,224人围观)

还没有评论,来说两句吧...

相关阅读