一开始想的是生成一种程序进行一次判断,后来想想,这样基本就减不了枝了,边生成程序边进行操作的话还有可能达到剪枝的效果,于是用了10个stack,用于存放操作数,10个辅助stack,用于操作回滚,然后每生成一条指令,就对10个stack进行一次操作,有一个发生error的时候,就可以剪枝回滚,如果都操作正常,则进行下一条指令的生成,由于还要求在生成程序最短的情况下使得字典序最小,因此在产生指令的时候可以依add->div->dup->mul->sub的顺序进行搜索,这样当发现一个程序满足条件时,一定是最短且字典序最小的:
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
const char* commands[] = {
"ADD", "DIV", "DUP", "MUL", "SUB"
};
const int limit = 30000;
int n, x[10], y[10];
vector<int> stack[10], instructions, history[10];
void print()
{
if(instructions.empty()){
puts("Empty sequence");
return;
}
printf("%s", commands[instructions[0]]);
for(int i = 1; i < instructions.size(); ++i) printf(" %s", commands[instructions[i]]);
puts("");
}
bool add(vector<int>& v, vector<int>& h)
{
int n = v.size(), r;
if(n < 2) return false;
r = v[n-1] + v[n-2];
if(abs(r) > limit) return false;
h.push_back(v[n-1]);
h.push_back(v[n-2]);
v.pop_back();
v.back() = r;
return true;
}
bool div(vector<int>& v, vector<int>& h)
{
int n = v.size(), r;
if(n < 2) return false;
if(v.back() == 0) return false;
r = v[n-2] / v[n-1];
if(abs(r) > limit) return false;
h.push_back(v[n-1]);
h.push_back(v[n-2]);
v.pop_back();
v.back() = r;
return true;
}
bool dup(vector<int>& v, vector<int>& h)
{
int n = v.size(), r;
if(n < 1) return false;
v.push_back(v.back());
return true;
}
bool mul(vector<int>& v, vector<int>& h)
{
int n = v.size(), r;
if(n < 2) return false;
r = v[n-1] * v[n-2];
if(abs(r) > limit) return false;
h.push_back(v[n-1]);
h.push_back(v[n-2]);
v.pop_back();
v.back() = r;
return true;
}
bool sub(vector<int>& v, vector<int>& h)
{
int n = v.size(), r;
if(n < 2) return false;
r = v[n-2] - v[n-1];
if(abs(r) > limit) return false;
h.push_back(v[n-1]);
h.push_back(v[n-2]);
v.pop_back();
v.back() = r;
return true;
}
bool simulate(int i, int j)
{
switch(i){
case 0: return add(stack[j], history[j]);
case 1: return div(stack[j], history[j]);
case 2: return dup(stack[j], history[j]);
case 3: return mul(stack[j], history[j]);
default: return sub(stack[j], history[j]);
}
}
void rewind(int i, int j)
{
if(i == 2) stack[j].pop_back();
else{
stack[j].back() = history[j].back(); history[j].pop_back();
stack[j].push_back(history[j].back()); history[j].pop_back();
}
}
bool dfs(int k)
{
if(!k){
for(int i = 0; i < n; ++i){
if(!(stack[i].size() == 1 && stack[i][0] == y[i])) return false;
}
return true;
}
int i, j;
for(i = 0; i < 5; ++i){
for(j = 0; j < n; ++j){
if(!simulate(i, j)) break;
}
if(j < n){
for(--j; j > -1; --j) rewind(i, j);
continue;
}
instructions.push_back(i);
if(dfs(k - 1)) return true;
for(--j; j > -1; --j) rewind(i, j);
instructions.pop_back();
}
return false;
}
int main()
{
int t = 0, i, j;
while(scanf("%d", &n), n){
for(i = 0; i < n; ++i) scanf("%d", x + i);
for(i = 0; i < n; ++i) scanf("%d", y + i);
printf("Program %d\n", ++t);
instructions.clear();
for(i = 0; i < 11; ++i){
for(j = 0; j < n; ++j){
stack[j].clear();
stack[j].push_back(x[j]);
}
if(dfs(i)) break;
}
if(i < 11) print(), puts("");
else puts("Impossible\n");
}
return 0;
}