题意:有n个栈,然后对于每个栈都有取栈顶两个值加减乘除得到一个数子压栈,或取栈顶的数字复制一个压栈,一共5种操作,刚开始每个栈都有一个初始值,n个数字可以经过同样的最多10个操作后使初始值变为给出的目标值且栈里数字都唯一。要求按顺序输出操作,最短且按字典序。
题解:先bfs求第一组解,然后用同样操作看是否能让其他n-1组解也成立。
#include <stdio.h>
#include <queue>
#include <stack>
using namespace std;
const int N = 15;
struct bgm {
stack<int> s;
int step;
int path[N];
int num1, num2;
};
int a1[N], a2[N], n;
char flag[][N] = {"ADD", "DIV", "DUP", "MUL", "SUB"};
bgm solve(int ch, bgm a) {
int temp1, temp2;
if (ch != 2) {
temp1 = a.s.top();
a.s.pop();
temp2 = a.s.top();
a.s.pop();
}
if (ch == 0)
a.s.push(temp1 + temp2);
else if (ch == 1)
a.s.push(temp2 / temp1);
else if (ch == 3)
a.s.push(temp1 * temp2);
else if (ch == 4)
a.s.push(temp2 - temp1);
else {
int temp = a.s.top();
a.s.push(temp);
}
return a;
}
bool judge(bgm a) {
for (int i = 1; i < n; i++) {
bgm b;
b.s.push(a1[i]);
for (int j = 0; j < a.step; j++) {
if (a.path[j] == 1 && b.s.top() == 0 || b.s.top() > 30000 || b.s.top() < -30000)
return false;
b = solve(a.path[j], b);
}
if (b.s.top() != a2[i])
return false;
}
return true;
}
bool bfs(int st, int en) {
queue<bgm> q;
while (!q.empty())
q.pop();
bgm a;
a.s.push(st);
a.step = 0;
q.push(a);
while (!q.empty()) {
bgm u = q.front();
q.pop();
for (int i = 0; i < 5; i++) {
if (u.s.size() == 1 && i != 2) continue;
if (u.s.top() == 0 && i == 1) continue;
bgm u1 = solve(i, u);
if (u1.s.top() > 30000 || u1.s.top() < -30000)
continue;
u1.path[u1.step++] = i;
if (u1.s.size() == 1 && u1.s.top() == en) {
if (judge(u1)) {
printf("%s", flag[u1.path[0]]);
for (int j = 1; j < u1.step; j++)
printf(" %s", flag[u1.path[j]]);
printf("\n\n");
return true;
}
}
if (u1.step < 10)
q.push(u1);
}
}
return false;
}
int main() {
int cas = 1;
while (scanf("%d", &n) == 1 && n) {
for (int i = 0; i < n; i++)
scanf("%d", &a1[i]);
for (int i = 0; i < n; i++)
scanf("%d", &a2[i]);
printf("Program %d\n", cas++);
int flag1 = 0;
for (int i = 0; i < n; i++)
if (a1[i] != a2[i]) {
flag1 = 1;
break;
}
if (!flag1)
printf("Empty sequence\n\n");
else if (!bfs(a1[0], a2[0]))
printf("Impossible\n\n");
}
return 0;
}