Description
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 quotient , 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:
A DIV-command is executed, and the top-most element of the stack is 0.
A ADD, SUB, MUL or DIV-command is executed when the stack contains only one element.
An operation produces a value greater than 30000 in absolute value.
Input
The input consists of a series of function descriptions. Each description starts with a line containing a single integer n (n <= 10), the number of input/output pairs to follow. The following two lines contains n integers each: x1, x2, ..., xn in the first line (all different), and y1, y2, ..., yn in the second line. The numbers will be no more than 30000 in absolute value.
The input is terminated by a test case starting with n = 0. This test case should not be processed.
Output
You are to find the shortest program that computes a function f , such that f(xi) = yi for all 1 <= i <= n. This implies that the program you output may not enter an error state if executed on the inputs xi (although it may enter an error state for other inputs). Consider only programs that have at most 10 statements.
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.
Sample Input
4
1 2 3 4
0 -2 -6 -12
3
1 2 3
1 11 1998
1
1998
1998
0
Sample Output
Program 1
DUP DUP MUL SUB
Program 2
Impossible
Empty sequence
这其实是一道搜索题,只是和栈有一点关系而已,不过我一直没注意输出错了多次,另外一个主意整除,可能
除数为0,所以需要判断,只需要搜索第一个数成立的情况,保存操作,然后判断后面的是否都符合条件。
#include <stdio.h> #include <stack> #define INF 30005 const int maxn = 15; char op[5][maxn] = { "ADD", "DIV", "DUP", "MUL", "SUB" }; int x[maxn], y[maxn], ans, pos[maxn], t[maxn], n; std :: stack < int > s; inline int abs ( int v ) { return v < 0 ? -v : v; } int is_ok ( int d ) { for ( int i = 1; i < n; i ++ ) { std :: stack < int > temp; while ( temp.size ( ) >= 1 ) //清空栈 temp.pop ( ); temp.push ( x[i] ); //加进一个数 for ( int j = 0; j < d; j ++ ) { int a, b, v; if ( t[j] != 2 ) { b = temp.top ( ); temp.pop ( ); a = temp.top ( ); temp.pop ( ); switch ( t[j] ) { case 0 : if ( abs ( a+b ) > INF ) //超过操作运算的范围 return 0; temp.push ( a+b ); break ; case 1 : if ( b == 0 || abs ( a/b ) > INF ) return 0; temp.push ( a/b ); break ; case 3 : if ( abs ( a*b ) > INF ) return 0; temp.push ( a*b ); break ; case 4 : if ( abs ( a-b ) > INF ) return 0; temp.push ( a-b ); break ; } } else { v = temp.top ( ); temp.push ( v ); } } int v = temp.top ( ); if ( v != y[i] ) //不相等就直接返回 return 0; } return 1; } void dfs ( int d, int k ) { if ( d > 10 || d >= ans ) //超过10层或答案不能更优 return ; int u = s.top ( ); if ( s.size ( ) == 1 && u == y[0] && is_ok ( d ) ) { ans = d; for ( int i = 0; i < d; i ++ ) //保存操作 pos[i] = t[i]; return ; } if ( s.size ( ) > 1 ) //操作数大于1时可以运算 { int b = s.top ( ); s.pop ( ); int a = s.top ( ); s.pop ( ); if ( abs ( a+b ) <= INF ) { t[d] = 0; s.push ( a+b ); dfs ( d+1, k ); s.pop ( ); } if ( b && abs ( a/b ) <= INF ) //考虑b为0 { t[d] = 1; s.push ( a/b ); dfs ( d+1, k ); s.pop ( ); //回溯 } s.push ( a ); //注意回溯 s.push ( b ); } if ( k < 10 ) //复制超过10次运算也会超过十次 { t[d] = 2; int v = s.top ( ); s.push ( v ); dfs ( d+1, k+1 ); s.pop ( ); } if ( s.size ( ) > 1 ) { int b = s.top ( ); s.pop ( ); int a = s.top ( ); s.pop ( ); if ( abs ( a*b ) <= INF ) { t[d] = 3; s.push ( a*b ); dfs ( d+1, k ); s.pop ( ); } if ( abs ( a-b ) <= INF ) { t[d] = 4; s.push ( a-b ); dfs ( d+1, k ); s.pop ( ); } s.push ( a ); s.push ( b ); } } int main ( ) { int cas = 1; while ( ~ scanf ( "%d", &n ) && n ) { ans = maxn; while ( s.size ( ) >= 1 ) s.pop ( ); for ( int i = 0; i < n; i ++ ) scanf ( "%d", &x[i] ); for ( int i = 0; i < n; i ++ ) scanf ( "%d", &y[i] ); s.push ( x[0] ); //需要加第一个数 dfs ( 0, 0 ); printf ( "Program %d\n", cas ++ ); if ( ans == maxn ) printf ( "Impossible\n" ); else if ( ans == 0 ) printf ( "Empty sequence\n" ); else { printf ( "%s", op[pos[0]] ); for ( int i = 1; i < ans; i ++ ) printf ( " %s", op[pos[i]] ); printf ( "\n" ); } printf ( "\n" ); //最后一个空行 } return 0; }