• POJ 1222 EXTENDED LIGHTS OUT 反转+点灯游戏


    一、题目大意

    5行6列的格子里,30盏灯,给出起始状态,让我们找到点亮哪些灯可以让这些灯全亮。(0代表亮,1代表不亮)

    二、解题思路

    定义一个数组f[i][j],代表第i行第j列这个点是否被点过,1代表点过,0代表没点过。

    利用二进制数的方式,枚举f[i][j]第一行的所有情况 000000 000001 000010 000011 ... 111111,

    然后从第2行到第5行循环所有格子i和j,计算f[i-1]+f[i-2][j]+f[i-1][j-1]+f[i-1][j+1]和i-1 j 的起始状态,可以直到i-1 j位置的灯是否为亮的,如果它不亮,那么电亮 f[i][j]

    最后判断下f[5][i](最后一行),如果最后一行 的灯全亮,那么这是一个可行解,总和为f[i][j]求sum,如果最后一行灯不全亮,循环下一次。

    判断某一个位置i j的灯是不是亮,比较简单,就是把 f[i-1][j]+f[i+1][j]+f[i][j]+f[i][j-1]+f[i][j+1]求和,判断下是不是奇数,如果时奇数,这个位置的明暗程度与起始相反,否则相同。

    三、代码

    1. #include
    2. using namespace std;
    3. bool lightOn[10][10];
    4. int revCnt[10][10], ansCnt, ans[10][10], towPow[27];
    5. void initTwoPow()
    6. {
    7. towPow[0] = 1;
    8. for (int i = 1; i <= 20; i++)
    9. {
    10. towPow[i] = towPow[i - 1] * 2;
    11. }
    12. }
    13. void input()
    14. {
    15. ansCnt = 0x3f3f3f3f;
    16. int x;
    17. for (int i = 1; i <= 5; i++)
    18. {
    19. for (int j = 1; j <= 6; j++)
    20. {
    21. scanf("%d", &x);
    22. if (x == 0)
    23. {
    24. lightOn[i][j] = true;
    25. }
    26. else
    27. {
    28. lightOn[i][j] = false;
    29. }
    30. }
    31. }
    32. }
    33. int calcRevCntAroundIJ(int i, int j)
    34. {
    35. int result = revCnt[i][j];
    36. if (i > 1)
    37. {
    38. result += revCnt[i - 1][j];
    39. }
    40. if (j > 1)
    41. {
    42. result += revCnt[i][j - 1];
    43. }
    44. if (j < 6)
    45. {
    46. result += revCnt[i][j + 1];
    47. }
    48. if (i < 5)
    49. {
    50. result += revCnt[i + 1][j];
    51. }
    52. return result;
    53. }
    54. // 最后一行灯全亮吗
    55. bool isLastLineLightOn()
    56. {
    57. for (int col = 1; col <= 6; col++)
    58. {
    59. int lastLineRevCnt = calcRevCntAroundIJ(5, col);
    60. bool lastLineLightOn = lightOn[5][col];
    61. if (lastLineRevCnt % 2 != 0)
    62. {
    63. lastLineLightOn = !lightOn[5][col];
    64. }
    65. if (!lastLineLightOn)
    66. {
    67. return false;
    68. }
    69. }
    70. return true;
    71. }
    72. // 保存结果
    73. void saveAns()
    74. {
    75. int currentAnsCnt = 0;
    76. for (int i = 1; i <= 5; i++)
    77. {
    78. for (int j = 1; j <= 6; j++)
    79. {
    80. currentAnsCnt += revCnt[i][j];
    81. }
    82. }
    83. if (currentAnsCnt >= ansCnt)
    84. {
    85. return;
    86. }
    87. for (int i = 1; i <= 5; i++)
    88. {
    89. for (int j = 1; j <= 6; j++)
    90. {
    91. ans[i][j] = revCnt[i][j];
    92. }
    93. }
    94. }
    95. // solve的核心思想时第i行确定把第i-1行全部电亮
    96. void solve()
    97. {
    98. for (int i = 2; i <= 5; i++)
    99. {
    100. for (int j = 1; j <= 6; j++)
    101. {
    102. int beforeLineRevCnt = calcRevCntAroundIJ(i - 1, j);
    103. bool beforeLineLightOn = lightOn[i - 1][j];
    104. if (beforeLineRevCnt % 2 != 0)
    105. {
    106. beforeLineLightOn = !lightOn[i - 1][j];
    107. }
    108. if (!beforeLineLightOn)
    109. {
    110. revCnt[i][j] = 1;
    111. }
    112. }
    113. }
    114. }
    115. void flushRevCnt()
    116. {
    117. for (int i = 1; i <= 5; i++)
    118. {
    119. for (int j = 1; j <= 6; j++)
    120. {
    121. revCnt[i][j] = 0;
    122. }
    123. }
    124. }
    125. void handleFirstLineByBin(int binNum)
    126. {
    127. for (int i = 5; i >= 0; i--)
    128. {
    129. int current = binNum & towPow[i];
    130. current = current >> i;
    131. if (current == 1)
    132. {
    133. revCnt[1][6 - i] = 1;
    134. }
    135. else
    136. {
    137. revCnt[1][6 - i] = 0;
    138. }
    139. }
    140. }
    141. void outputAns()
    142. {
    143. for (int i = 1; i <= 5; i++)
    144. {
    145. for (int j = 1; j <= 6; j++)
    146. {
    147. if (j == 6)
    148. {
    149. printf("%d\n", ans[i][j]);
    150. }
    151. else
    152. {
    153. printf("%d ", ans[i][j]);
    154. }
    155. }
    156. }
    157. }
    158. int main()
    159. {
    160. initTwoPow();
    161. int t = 0;
    162. scanf("%d", &t);
    163. for (int m = 1; m <= t; m++)
    164. {
    165. input();
    166. int base = 1024;
    167. for (int i = 0; i < towPow[6]; i++)
    168. {
    169. int binNum = base + i;
    170. flushRevCnt();
    171. handleFirstLineByBin(binNum);
    172. solve();
    173. if (isLastLineLightOn())
    174. {
    175. saveAns();
    176. }
    177. }
    178. printf("PUZZLE #%d\n", m);
    179. outputAns();
    180. }
    181. return 0;
    182. }

  • 相关阅读:
    R语言ggplot2可视化:可视化折线图、使用labs函数为折线图添加自定义的X轴标签信息
    再谈GOF设计模式的设计原则
    玩机教程:阿里云无影云电脑怎么使用?
    问题:用来表示证券收益的波动性,值越大说明()。 #媒体#经验分享
    使用cython加速代码运行
    1688获得店铺详情 API 返回值说明
    米哈游、复旦发布,具备感知、大脑、行动的大语言模型“智能体”
    人工智能|深度学习——多模态条件机制 Cross Attention 原理及实现
    2、HTML基础 _列表、表格、表单标签和input、button按钮、select下拉菜单、textarea文本域、label标签
    tcpdump使用大全
  • 原文地址:https://blog.csdn.net/qq_53038151/article/details/132844768