[关闭]
@zhutoulwz 2014-11-04T13:40:42.000000Z 字数 2278 阅读 2003

sicily 1107 Simple Puzzle

sicily ACM


1. 题目大意

有n个数字,长度均为k,现在把这n个数对齐成k列,那么就有n行k列,然后把每一个数擦去一个数,擦去的数所在的列都不相同,而且擦去的数也各不相同,剩下n个不完整的数。输入这n个不完整的数,求出原来的n个数。如果有多个解,排序输出。

2. 题目数据范围

题目没有明显指出,不过可以推断出来。因为有n个数,每个数当中擦去一个数字,那么总共擦掉n个数字,这n个数字又各不一样,所以n最大为10,即1 <= n <= 10

3. 解题思路

首先想到的是枚举。对每个数缺失的位置,每个位置缺失的数进行枚举,然后计算所有数的和与输入的和是否相等,如果相等,则为其中一种可能,记下结果。枚举完成后,对结果进行排序输出。排序规则:比较第1个数,较小的排在前面,如果第1个数相等,则比较第2个数,依此类推。

4. 代码

  1. // 1107.cpp
  2. #include <iostream>
  3. #include <memory.h>
  4. #include <cstdio>
  5. #include <algorithm>
  6. #include <vector>
  7. using namespace std;
  8. string numbers[20];
  9. int counter, sum, len;
  10. struct Node{
  11. int index, digit;
  12. };
  13. Node digits[20]; // 保存给每个数填充的数的位置及值
  14. vector<int> ans[100];
  15. int ans_counter;
  16. bool vis[20], vis2[20]; // vis保存某列是否已填充数字, vis2保存某数字是否已经被填了
  17. void cal()
  18. {
  19. int total = 0;
  20. vector<int> v;
  21. bool valid = true;
  22. for (int i = 0; i < counter; i++)
  23. {
  24. int temp = 0;
  25. // 这里判断首位不是为0,
  26. //虽然保证了添加的数字为第一个的时候不为0,但输入的不完整的数可能0(为0的情况就只能在0的前面填上不为0的数字)
  27. if (numbers[i][0] == '0' && digits[i].index > 0)
  28. {
  29. valid = false;
  30. break;
  31. }
  32. // 计算当前第i个数的值
  33. for (int j = 0; j < digits[i].index; j++)
  34. {
  35. temp *= 10;
  36. temp += (int) (numbers[i][j] - '0');
  37. }
  38. temp *= 10;
  39. temp += digits[i].digit;
  40. for (int j = digits[i].index; j < len; j++)
  41. {
  42. temp *= 10;
  43. temp += (int) (numbers[i][j] - '0');
  44. }
  45. v.push_back(temp);
  46. total += temp;
  47. }
  48. if (total == sum && valid)
  49. {
  50. ans[ans_counter ++] = v;
  51. }
  52. }
  53. void dfs(int k)
  54. {
  55. if (k == counter) // 已经填完了n个数
  56. {
  57. cal();
  58. return;
  59. }
  60. for (int i = 0; i <= len; i++)
  61. {
  62. if (vis[i]) // 判断该列是否已经填了数字
  63. continue;
  64. vis[i] = true;
  65. for (int j = 0; j <= 9; j++)
  66. {
  67. if (i == 0 && j == 0) // 首位不能为0
  68. continue;
  69. if (vis2[j]) // 判断该数字是否被填了
  70. continue;
  71. else{
  72. digits[k].index = i;
  73. digits[k].digit = j;
  74. vis2[j] = true;
  75. dfs(k + 1);
  76. vis2[j] = false;
  77. }
  78. }
  79. vis[i] = false;
  80. }
  81. }
  82. bool cmp(vector<int> a, vector<int> b)
  83. {
  84. for (int i = 0; i < counter; i ++)
  85. {
  86. if (a[i] != b[i])
  87. return a[i] < b[i];
  88. }
  89. return true;
  90. }
  91. int main()
  92. {
  93. int test;
  94. while (scanf ("%d", &test) && test != 0)
  95. {
  96. char ch;
  97. getchar();
  98. string num = "";
  99. counter = 0;
  100. ans_counter = 0;
  101. memset(vis, false, sizeof(vis));
  102. memset(vis2, false, sizeof(vis2));
  103. memset(ans, 0, sizeof(ans));
  104. memset(digits, 0, sizeof(digits));
  105. // 处理输入数据,将n个数保存在numbers数组里
  106. do{
  107. ch = getchar();
  108. if (ch == ' ')
  109. {
  110. numbers[counter++] = num;
  111. num = "";
  112. }
  113. else if (ch != '\n'){
  114. num += ch;
  115. }
  116. } while (ch != '\n');
  117. // 处理完输入后,counter值即为题目中的n
  118. len = numbers[0].size(); // len是不完整数的长度,即是k - 1
  119. sum = 0; // 用来保存n个数总和
  120. for (int i = 0; i < num.size(); i++)
  121. {
  122. sum *= 10;
  123. sum += (int) (num[i] - '0');
  124. }
  125. dfs(0); // 枚举状态
  126. sort(ans, ans + ans_counter, cmp); // 对结果进行排序
  127. if (ans_counter == 0)
  128. cout << test << ' ' << 0 << endl;
  129. else{
  130. // 注意输出格式
  131. for (int i = 0; i < ans_counter; i++)
  132. {
  133. cout << test;
  134. for (int j = 0; j < counter; j++)
  135. cout << ' ' << ans[i][j];
  136. cout << endl;
  137. }
  138. }
  139. }
  140. return 0;
  141. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注