UVa 656 - Optimal Programs (DFSID + 模拟 + 枚举)

题意

给出五个操作,和两个序列。

要求输出一种操作,使得从上一个序列的每个数可以变到下一个序列的每个数。

输出最小的操作数,如果相同,输出字典序最小的。

思路

没想到什么好的办法,暴力判断每一种操作,并记录

如果操作过后就是后来的那个数,然后对这个操作检查之后的所有数,如果都满足,输出。

因为感觉BFS会超内存,就用了DFSID

因为我是按照字典序来依次执行操作的,所以当有合适的操作时候他一定是字典序最小的。

代码

  
  
  
  
  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 = 150 + 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. string comd, str[] = {"ADD", "DIV", "DUP", "MUL", "SUB"};
  40. int n, ori[MAXN], fin[MAXN];
  41. bool flag;
  42. int Fun(int cmd, stack<int> &stk)
  43. {
  44. if (SZ(stk) == 1 && cmd != 2) return -1;
  45. if (cmd == 0) //ADD
  46. {
  47. int a = stk.top(); stk.pop();
  48. if (abs(a + stk.top()) > 30000)
  49. {
  50. stk.push(a);
  51. return -1;
  52. }
  53. stk.top() += a;
  54. }
  55. else if (cmd == 1) //DIV
  56. {
  57. if (stk.top() == 0) return -1;
  58. int a = stk.top(); stk.pop();
  59. stk.top() /= a;
  60. }
  61. else if (cmd == 2) //DUP
  62. stk.push(stk.top());
  63. else if (cmd == 3) //MUL
  64. {
  65. int a = stk.top(); stk.pop();
  66. if (abs(a * stk.top()) > 30000)
  67. {
  68. stk.push(a);
  69. return -1;
  70. }
  71. stk.top() *= a;
  72. }
  73. else
  74. {
  75. int a = stk.top(); stk.pop();
  76. if (abs(stk.top() - a) > 30000)
  77. {
  78. stk.push(a);
  79. return -1;
  80. }
  81. stk.top() -= a;
  82. }
  83. return 0;
  84. }
  85. bool Check(string cmd)
  86. {
  87. for (int i = 1; i < n; i++)
  88. {
  89. stack<int> stk;
  90. stk.push(ori[i]);
  91. for (int j = 0; j < SZ(cmd); j++)
  92. {
  93. int tmp = Fun(cmd[j] - '0', stk);
  94. if (tmp == -1) return false;
  95. }
  96. if (!(SZ(stk) == 1 && stk.top() == fin[i])) return false;
  97. }
  98. return flag = true;
  99. }
  100. void Goback(int fst, int sec, stack<int> &stk, int cmd)
  101. {
  102. if (cmd == 2) //DUP
  103. stk.pop();
  104. else
  105. {
  106. stk.pop();
  107. stk.push(sec);
  108. stk.push(fst);
  109. }
  110. }
  111. bool DFS(int cnt, string comd, stack<int> stk, int step)
  112. {
  113. if (cnt > step) return false;
  114. int fst = stk.top(); stk.pop();
  115. int sec = INF;
  116. if (!stk.empty()) sec = stk.top();
  117. stk.push(fst);
  118. for (int i = 0; i < 5; i++)
  119. {
  120. int tmp = Fun(i, stk);
  121. if (tmp == -1) continue; //此操作不合法
  122. char tempStr = i + '0';
  123. if (SZ(stk) == 1 && stk.top() == fin[0]) //此操作过后可以转换
  124. if (Check(comd + tempStr))
  125. {
  126. comd += tempStr;
  127. for (i = 0; i < SZ(comd); i++)
  128. if (i == 0) cout << str[comd[i] - '0'];
  129. else cout << " " << str[comd[i] - '0'];
  130. puts("");
  131. return true;
  132. }
  133. if (DFS(cnt + 1, comd + tempStr, stk, step)) return true;
  134. Goback(fst, sec, stk, i); //回到开始情况
  135. }
  136. return false;
  137. }
  138. int main()
  139. {
  140. //ROP;
  141. int i, j, cases = 0;
  142. while (scanf("%d", &n), n)
  143. {
  144. printf("Program %d\n", ++cases);
  145. flag = false;
  146. for (i = 0; i < n; i++) scanf("%d", &ori[i]);
  147. for (i = 0; i < n; i++) scanf("%d", &fin[i]);
  148. if (ori[0] == fin[0]) //先排除一下无操作的情况
  149. {
  150. for (i = 1; i < n; i++)
  151. if (ori[i] != fin[i]) break;
  152. if (i == n)
  153. {
  154. puts("Empty sequence");
  155. puts("");
  156. continue;
  157. }
  158. }
  159. for (int step = 2; step <= 10; step++)
  160. {
  161. if (flag) break;
  162. stack<int> stk; stk.push(ori[0]);
  163. DFS(1, "", stk, step);
  164. }
  165. if (!flag) puts("Impossible");
  166. puts("");
  167. }
  168. return 0;
  169. }

你可能感兴趣的:(ACM,uva)