[关闭]
@yuyuesheng 2019-02-20T13:19:44.000000Z 字数 1078 阅读 780

I - Problem J. Let Sudoku Rotate

题意:
给一个16*16的数独,每个4*4的子模块都有可能被逆时针转动过,问至少转动了多少次。
题解:
dfs枚举每一行的四个4*4的子模块的转动次数,在进行数独判断剪枝。

  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstring>
  4. using namespace std;
  5. const int maxn = 20;
  6. char s[maxn][maxn];
  7. int sudu[maxn][maxn], ans;
  8. int vis[maxn];
  9. void rot(int x, int y)
  10. {
  11. int t[5][5];
  12. for (int i = 0; i < 4; i++)
  13. for (int j = 0; j < 4; j++)
  14. t[j][3 - i] = sudu[x + i][y + j];
  15. for (int i = 0; i < 4; i++)
  16. for (int j = 0; j < 4; j++)
  17. sudu[x + i][y + j] = t[i][j];
  18. }
  19. int check(int x, int y)
  20. {
  21. for (int i = x; i < x + 4; i++)
  22. {
  23. memset(vis, 0, sizeof(vis));
  24. for (int j = 0; j < y + 4; j++)
  25. {
  26. vis[sudu[i][j]]++;
  27. if (vis[sudu[i][j]] >= 2)
  28. return 0;
  29. }
  30. }
  31. for (int i = y; i < y + 4; i++)
  32. {
  33. memset(vis, 0, sizeof(vis));
  34. for (int j = 0; j < x + 4; j++)
  35. {
  36. vis[sudu[j][i]]++;
  37. if (vis[sudu[j][i]] >= 2)
  38. return 0;
  39. }
  40. }
  41. return 1;
  42. }
  43. void dfs(int i, int j, int step)
  44. {
  45. if (i == 4)
  46. {
  47. ans = min(ans, step);
  48. return;
  49. }
  50. if (step >= ans)
  51. return;
  52. if (j == 4)
  53. dfs(i + 1, 0, step);
  54. for (int t = 0; t < 4; t++)
  55. {
  56. if (check(i * 4, j * 4))
  57. dfs(i, j + 1, step + t);
  58. rot(i * 4, j * 4);
  59. }
  60. }
  61. void solve()
  62. {
  63. for (int i = 0; i < 16; i++)
  64. {
  65. cin >> s[i];
  66. for (int j = 0; j < 16; j++)
  67. {
  68. if (isdigit(s[i][j]))
  69. sudu[i][j] = s[i][j] - '0';
  70. else
  71. sudu[i][j] = s[i][j] - 'A' + 10;
  72. }
  73. }
  74. ans = 16 * 4;
  75. dfs(0, 0, 0);
  76. cout << ans << endl;
  77. }
  78. int main()
  79. {
  80. int t;
  81. cin >> t;
  82. while (t--)
  83. solve();
  84. return 0;
  85. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注