As you know, writing programs is often far from being easy. Things become even harder if your programs have to be as fast as possible. And sometimes there is reason for them to be. Many large programs such as operating systems or databases have ``bottlenecks'' - segments of code that get executed over and over again, and make up for a large portion of the total running time. Here it usually pays to rewrite that code portion in assembly language, since even small gains in running time will matter a lot if the code is executed billions of times.
In this problem we will consider the task of automating the generation of optimal assembly code. Given a function (as a series of input/output pairs), you are to come up with the shortest assembly program that computes this function.
The programs you produce will have to run on a stack based machine, that supports only five commands: ADD,SUB, MUL, DIV and DUP. The first four commands pop the two top elements from the stack and push their sum, difference, product or integer quotient1 , respectively, on the stack. The DUP command pushes an additional copy of the top-most stack element on the stack.
So if the commands are applied to a stack with the two top elements a and b (shown to the left), the resulting stacks look as follows:
At the beginning of the execution of a program, the stack will contain a single integer only: the input. At the end of the computation, the stack must also contain only one integer; this number is the result of the computation.
There are three cases in which the stack machine enters an error state:
The input is terminated by a test case starting with n = 0. This test case should not be processed.
For each function description, output first the number of the description. Then print out the se- quence of commands that make up the shortest program to compute the given function. If there is more than one such program, print the lexicographically smallest. If there is no program of at most 10 statements that computes the function, print the string ``Impossible''. If the shortest program consists of zero commands, print ``Empty sequence''.
Output a blank line after each test case.
4 1 2 3 4 0 -2 -6 -12 3 1 2 3 1 11 1998 1 1998 1998 0
Program 1 DUP DUP MUL SUB Program 2 Impossible Program 3 Empty sequence
//http://uva.onlinejudge.org/external/6/656.html #include<cstdio> #include<cstring> #include<cmath> #include<stack> #include<queue> using namespace std; const int maxn=10+5; const char * tr[] = {"ADD", "DIV", "DUP", "MUL", "SUB"}; enum op_e { ADD, DIV, DUP, MUL, SUB}; struct State { State() { memset(path, 0, sizeof(path)); pathn=0; } stack<int> s; int path[maxn]; int pathn; }ans; int x[maxn], y[maxn]; int n; void init() { for(int i=0; i<n; i++) scanf("%d", x+i); for(int i=0; i<n; i++) scanf("%d", y+i); } // return true if trans is valid and modified t bool trans(State& t, int i) { stack<int> &s = t.s; //A ADD, SUB, MUL or DIV-command is executed when the stack contains only one element. if(i!=DUP && s.size()==1) return false; int a=s.top(); if(i==DIV && a==0) return false; //当前栈的大小减去剩余步骤的大小,如果大于1,说明永远达不到目标(假设后面不是dup命令,则栈大小都是减一) int len=s.size()-(10-t.pathn); if(len>1) return false; //ok, now all options are valid if(i==DUP) { s.push(a); t.path[t.pathn++]=i; return true; } s.pop();//pop a int b=s.top(); s.pop(); switch(i) { case ADD: s.push(a+b); break; case SUB: s.push(b-a); break; case MUL: s.push(b*a); break; case DIV: s.push(b/a); break; } if(abs(s.top())>30000) return false; t.path[t.pathn++]=i; return true; } bool checkOthers() { for (int i = 1; i < n; i++) { State t; t.s.push(x[i]); for(int j=0; j<ans.pathn; j++) { if(!trans(t, ans.path[j])) return false; } if(t.s.top()!=y[i]) return false; } return true; } bool bfs() { queue<State> q; ans = State(); State state; state.s.push(x[0]); q.push(state); while(!q.empty()) { State front = q.front(); q.pop(); if(front.s.size()==1 && front.s.top()==y[0]) { ans = front; if(checkOthers()) return true; } //已经10个了,不能再添加了 if(front.pathn==10) continue; for(int i=ADD;i<=SUB;i++) { State t=front; if(trans(t, i)) q.push(t); } } return false; } void solve() { if (bfs()) { if (ans.pathn == 0) printf("Empty sequence\n"); else { for (int i = 0; i < ans.pathn - 1; i ++) printf("%s ", tr[ans.path[i]]); printf("%s\n", tr[ans.path[ans.pathn - 1]]); } } else printf("Impossible\n"); printf("\n"); } int main() { #ifndef ONLINE_JUDGE freopen("./uva656.in", "r", stdin); #endif int kase=0; while(scanf("%d", &n)!=EOF && n) { init(); printf("Program %d\n", ++kase); solve(); } return 0; }