UVa 1377 - Ruler(BFS)

题意

给出一些数字,要求输出一些标记,根据这些标记可以得到上面的所有数字。

思路

一开始写了个贪心,后来发现不行。又写了个DFS,TLE了。最后还是看了帆神和柯神的题解。

这里好像有个YY的结论:最后所选的标号要么是给出的,要么是他们之间的差。

用BFS。不过好像所用的最长长度不能超过输入的最长,题目没说。感觉不太科学。

然后就是每走一步就加上每一个还没选到的值的和和差。我用了set判重。

代码

 
 
  1. #include <cstdio>
  2. #include <stack>
  3. #include <set>
  4. #include <iostream>
  5. #include <string>
  6. #include <vector>
  7. #include <queue>
  8. #include <functional>
  9. #include <cstring>
  10. #include <algorithm>
  11. #include <cctype>
  12. #include <ctime>
  13. #include <string>
  14. #include <map>
  15. #include <iomanip>
  16. #include <cmath>
  17. #define LL long long
  18. #define ULL unsigned long long
  19. #define SZ(x) (int)x.size()
  20. #define Lowbit(x) ((x) & (-x))
  21. #define MP(a, b) make_pair(a, b)
  22. #define MS(arr, num) memset(arr, num, sizeof(arr))
  23. #define PB push_back
  24. #define F first
  25. #define S second
  26. #define ROP freopen("input.txt", "r", stdin);
  27. #define MID(a, b) (a + ((b - a) >> 1))
  28. #define LC rt << 1, l, mid
  29. #define RC rt << 1|1, mid + 1, r
  30. #define LRT rt << 1
  31. #define RRT rt << 1|1
  32. #define BitCount(x) __builtin_popcount(x)
  33. #define BitCountll(x) __builtin_popcountll(x)
  34. #define LeftPos(x) 32 - __builtin_clz(x) - 1
  35. #define LeftPosll(x) 64 - __builtin_clzll(x) - 1
  36. const double PI = acos(-1.0);
  37. const int INF = 0x3f3f3f3f;
  38. using namespace std;
  39. const double eps = 1e-6;
  40. const int MAXN = 50 + 10;
  41. const int MOD = 1000007;
  42. typedef pair<int, int> pii;
  43. typedef vector<int>::iterator viti;
  44. typedef vector<pii>::iterator vitii;
  45. struct STATE
  46. {
  47. int ans;
  48. set<int> st;
  49. }ans;
  50. map<int, int> mp;
  51. vector<int> num;
  52. set<int> iniNum, vis;
  53. int n;
  54. void Init()
  55. {
  56. mp.clear(); num.clear(); iniNum.clear(); vis.clear();
  57. for (int i = 0; i < n; i++)
  58. {
  59. int tmp;
  60. scanf("%d", &tmp);
  61. if (!iniNum.count(tmp))
  62. {
  63. num.push_back(tmp);
  64. iniNum.insert(tmp);
  65. }
  66. }
  67. sort(num.begin(), num.end());
  68. for (int i = 0; i < SZ(num); i++) mp[num[i]] = i;
  69. ans.ans = 0, ans.st.clear();
  70. }
  71. STATE Add(int num, STATE cur)
  72. {
  73. for (set<int>::iterator it = cur.st.begin(); it != cur.st.end(); it++)
  74. {
  75. int tmp = abs(*it - num);
  76. if (mp.count(tmp)) cur.ans |= (1 << mp[tmp]);
  77. }
  78. cur.st.insert(num);
  79. return cur;
  80. }
  81. void BFS()
  82. {
  83. STATE cur;
  84. queue<STATE> qu;
  85. cur.ans = 0, cur.st.insert(0);
  86. qu.push(cur);
  87. int result = (1 << SZ(num)) - 1;
  88. while (!qu.empty())
  89. {
  90. cur = qu.front(); qu.pop();
  91. if (cur.ans == result)
  92. {
  93. if (SZ(ans.st) == 0) ans = cur;
  94. else
  95. {
  96. if (SZ(cur.st) > SZ(ans.st)) return;
  97. else if (SZ(ans.st) > SZ(cur.st)) ans = cur;
  98. else if (*ans.st.rbegin() > *cur.st.rbegin()) ans = cur;
  99. }
  100. }
  101. else
  102. {
  103. if (SZ(cur.st) > 7) continue;
  104. for (int i = 0; i < SZ(num); i++)
  105. {
  106. if (((1 << i) & cur.ans) == 0)
  107. {
  108. for (set<int>::iterator it = cur.st.begin(); it != cur.st.end(); it++)
  109. {
  110. if (*it + num[i] <= *(--num.end()))
  111. {
  112. STATE tmp = Add(*it + num[i], cur);
  113. if (!vis.count(tmp.ans)) qu.push(tmp);
  114. vis.insert(tmp.ans);
  115. }
  116. if (*it > num[i])
  117. {
  118. STATE tmp = Add(*it - num[i], cur);
  119. if (!vis.count(tmp.ans)) qu.push(tmp);
  120. vis.insert(tmp.ans);
  121. }
  122. }
  123. }
  124. }
  125. }
  126. }
  127. }
  128. int main()
  129. {
  130. //ROP;
  131. int i, j, cases = 0;
  132. while (scanf("%d", &n), n)
  133. {
  134. Init();
  135. BFS();
  136. printf("Case %d:\n", ++cases);
  137. printf("%d\n", SZ(ans.st));
  138. set<int>::iterator it = ans.st.begin();
  139. for (; it != ans.st.end(); it++)
  140. {
  141. if (it == ans.st.begin()) printf("%d", *it);
  142. else printf(" %d", *it);
  143. }
  144. puts("");
  145. }
  146. return 0;
  147. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值