UVa 225 - Golygons (回溯 + 剪枝)

题意

一个人要探索城市。

他有特殊的看风景技巧。

第一次他走一步,停下来看一下风景,然后左转或者右转走2步,看一下风景,再左转或者右转,走3步,看风景。最后走len步正好回到原点。

看过的风景不能再看

求他有几种看风景的方法,输出。

思路

最基本的思路是从起点开始,四个方向搜索、回溯,记录路径。

然后说说我的思路。

我用path记录路径,当判断回到终点的时候就push到vector里。

因为到达后只能左右走或者上下走(二维),所以我分开讨论,当从下面或者上面走来的时候,和当从左边或者右边走来的时候。

关于坐标的处理,可能会有很多很大的障碍物,需要排除。 
然后统一加上某个数,相当于原点移位,处理负数。

代码里充斥着大量重复的代码,不优雅。大家看看思路就行。。

有一个相当重要的剪枝,来自帆神(http://blog.csdn.net/accelerator_/article/details/17804417)

如果走到一个地方剩下的步数回不到原点了,直接回溯。

代码

 
 
  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 <string>
  13. #include <map>
  14. #include <cmath>
  15. #define LL long long
  16. #define SZ(x) (int)x.size()
  17. #define Lowbit(x) ((x) & (-x))
  18. #define MP(a, b) make_pair(a, b)
  19. #define MS(arr, num) memset(arr, num, sizeof(arr))
  20. #define PB push_back
  21. #define F first
  22. #define S second
  23. #define ROP freopen("input.txt", "r", stdin);
  24. #define MID(a, b) (a + ((b - a) >> 1))
  25. #define LC rt << 1, l, mid
  26. #define RC rt << 1|1, mid + 1, r
  27. #define LRT rt << 1
  28. #define RRT rt << 1|1
  29. #define BitCount(x) __builtin_popcount(x)
  30. const double PI = acos(-1.0);
  31. const int INF = 0x3f3f3f3f;
  32. using namespace std;
  33. const int MAXN = 200 + 10;
  34. const int MOD = 1e9 + 7;
  35. const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
  36. typedef pair<int, int> pii;
  37. typedef vector<int>::iterator viti;
  38. typedef vector<pii>::iterator vitii;
  39. int len, mp[MAXN][MAXN], vis[MAXN][MAXN];
  40. int sum[30];
  41. const int O = 100;
  42. string str = "nswe";
  43. vector<string> ans;
  44. void DFS(int x, int y, int step, int lastDir, string path)
  45. {
  46. //dir = 0, 下面走来的, 1上面走来, 2右边走来,3左边走来
  47. if (abs(x - O) + abs(y - O) > sum[len] - sum[step]) return;
  48. if (x == O && y == O)
  49. {
  50. if (step == len) ans.PB(path);
  51. return;
  52. }
  53. if (step == len) return;
  54. if (lastDir == 0 || lastDir == 1)
  55. {
  56. for (int i = 2; i < 4; i++)
  57. {
  58. bool flag = false;
  59. int xx = x + dir[i][0] * (step + 1), yy = y + dir[i][1] * (step + 1);
  60. if (xx < 0 || yy < 0) continue;
  61. if (i == 2)
  62. {
  63. for (int k = yy; k < y; k++)
  64. if (mp[xx][k])
  65. {
  66. flag = true;
  67. break;
  68. }
  69. }
  70. else
  71. {
  72. for (int k = y + 1; k <= yy; k++)
  73. if (mp[xx][k])
  74. {
  75. flag = true;
  76. break;
  77. }
  78. }
  79. if (!flag)
  80. if (!mp[xx][yy] && !vis[xx][yy])
  81. {
  82. vis[xx][yy] = 1;
  83. DFS(xx, yy, step + 1, i, path + str[i]);
  84. vis[xx][yy] = 0;
  85. }
  86. }
  87. }
  88. else
  89. {
  90. for (int i = 0; i < 2; i++)
  91. {
  92. bool flag = false;
  93. int xx = x + dir[i][0] * (step + 1), yy = y + dir[i][1] * (step + 1);
  94. if (xx < 0 || yy < 0) continue;
  95. if (i == 0)
  96. {
  97. for (int k = xx; k < x; k++)
  98. if (mp[k][yy])
  99. {
  100. flag = true;
  101. break;
  102. }
  103. }
  104. if (i == 1)
  105. for (int k = x + 1; k <= xx; k++)
  106. if (mp[k][yy])
  107. {
  108. flag = true;
  109. break;
  110. }
  111. if (!flag)
  112. if (!mp[xx][yy] && !vis[xx][yy])
  113. {
  114. vis[xx][yy] = 1;
  115. DFS(xx, yy, step + 1, i, path + str[i]);
  116. vis[xx][yy] = 0;
  117. }
  118. }
  119. }
  120. }
  121. void table()
  122. {
  123. sum[1] = 1;
  124. for (int i = 2; i <= 20; i++) sum[i] = i + sum[i - 1];
  125. }
  126. int main()
  127. {
  128. //ROP;
  129. int T, i, j, nblk;
  130. scanf("%d", &T);
  131. table();
  132. while (T--)
  133. {
  134. ans.clear(); MS(mp, 0);
  135. scanf("%d%d", &len, &nblk);
  136. while (nblk--)
  137. {
  138. int x, y;
  139. scanf("%d%d", &x, &y);
  140. if (abs(x) > O || abs(y) > O) continue;
  141. mp[O - y][x + O] = 1;
  142. }
  143. string path;
  144. for (int i = 0; i < 4; i++)
  145. {
  146. int x = dir[i][0] + O, y = dir[i][1] + O;
  147. vis[x][y] = 1;
  148. if (!mp[x][y])
  149. DFS(x, y, 1, i, path + str[i]);
  150. vis[x][y] = 0;
  151. }
  152. sort(ans.begin(), ans.end());
  153. for (i = 0; i < SZ(ans); i++) cout << ans[i] << endl;
  154. printf("Found %d golygon(s).\n\n", SZ(ans));
  155. }
  156. return 0;
  157. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值