pku 1480 Optimal Programs
题目地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1480
题目大意:
给你 x1 , x2 ,x3 ,x4,...xn
y1 ,y2 ,y3 ,y4,...yn
问是否存在一组运算顺序,使得f(xi) = =yi ( 1 <=i <= n ), 如果存在的话要输出运算次数最少的一组运算顺序,而且字典序要最小。
题意分析:
BFS + 大模拟,具体分析待填。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<cstdlib>
#include<cmath>
using namespace std;
int x[20],y[20];
stack< int >stk1[11], stk2[11];
char name[5][4]={"ADD", "DIV","DUP","MUL","SUB"};
int path[20];
int cnt = 0;
int n;
int ADD(stack<int>& s1, stack<int>& s2)
{
if(s1.size()<2)
return 0;
int opt1,opt2;
opt1 = s1.top();
s1.pop();
opt2 = s1.top();
s1.pop();
if(abs(opt1 + opt2) > 30000)
{
s1.push(opt2);
s1.push(opt1);
return 0;
}
s1.push(opt1 + opt2);
s2.push(opt1);
s2.push(opt2);
return 1;
}
int SUB(stack<int>& s1, stack<int>& s2)
{
if(s1.size() < 2)
return 0;
int opt1,opt2;
opt1 = s1.top();
s1.pop();
opt2 = s1.top();
s1.pop();
if(abs(opt2 - opt1) > 30000)
{
s1.push(opt2);
s1.push(opt1);
return 0;
}
s1.push(opt2 - opt1);
s2.push(opt1);
s2.push(opt2);
return 1;
}
int MUL(stack<int>& s1, stack<int>& s2)
{
if(s1.size() < 2)
return 0;
int opt1 ,opt2;
opt1 = s1.top();
s1.pop();
opt2 = s1.top();
s1.pop();
if(abs(opt1*opt2) > 30000)
{
s1.push(opt2);
s1.push(opt1);
return 0;
}
s1.push(opt1*opt2);
s2.push(opt1);
s2.push(opt2);
return 1;
}
int DIV(stack<int>& s1, stack<int>& s2)
{
if(s1.size() <2 ||s1.top() == 0)
return 0;
int opt1 ,opt2;
opt1 = s1.top();
s1.pop();
opt2 = s1.top();
s1.pop();
if(abs(opt2/opt1) > 30000)
{
s1.push(opt2);
s1.push(opt1);
return 0;
}
s1.push(opt2/opt1);
s2.push(opt1);
s2.push(opt2);
return 1;
}
int DUP(stack<int>& s1, stack<int>& s2)
{
if(s1.size()< 1 )
return 0;
s1.push(s1.top());
return 1;
}
void rewind(int i ,int j)
{
if(i != 2)
{
stk1[j].pop();
stk1[j].push(stk2[j].top()),stk2[j].pop();
stk1[j].push(stk2[j].top()),stk2[j].pop();
return ;
}
stk1[j].pop();
return;
}
int judge()
{
for(int i = 0 ;i < n; i++)
{
if(stk1[i].size() != 1||stk1[i].top() != y[i])
return 0;
}
return 1;
}
int DFS(int deep ,int h)
{
if(deep > h)
return 0;
if(judge())
return 1;
for(int i = 0 ;i < 5 ;i++)
{
int j;
switch(i)
{
case 0:
for(j = 0 ;j < n; j++)
if(!ADD(stk1[j],stk2[j]))
break;
break;
case 1:
for(j= 0 ;j < n; j++)
if(!DIV(stk1[j],stk2[j]))
break;
break;
case 2:
for(j= 0 ;j < n; j++)
if(!DUP(stk1[j],stk2[j]))
break;
break;
case 3:
for(j= 0 ;j < n; j++)
if(!MUL(stk1[j],stk2[j]))
break;
break;
case 4:
for(j= 0 ;j < n; j++)
if(!SUB(stk1[j],stk2[j]))
break;
break;
}
if(j < n)
{
for(int k = (-- j ); k >=0 ; k--)
rewind(i , k);
continue;
}
path[ cnt++ ] = i;
if(DFS(deep + 1, h))
return 1;
for(int k = (-- j ); k >=0 ; k--)
rewind(i , k);
cnt--;
}
return 0;
}
int main()
{
int num = 0;
while(cin>> n)
{
num++;
if(n == 0)
break;
for(int i = 0 ;i < 11 ; i++)
{
while(!stk1[i].empty())
stk1[i].pop();
while(!stk2[i].empty())
stk2[i].pop();
}
cnt = 0;
for(int i = 0 ;i < n;i++ )
{
cin >> x[i];
stk1[i].push(x[i]);
}
int flag = 1;
for(int i= 0 ;i < n;i++)
{
cin >> y[i];
if(y[i] != x[i])
flag = 0;
}
printf("Program %d\n", num);
if(flag)
{
cout <<"Empty sequence\n" << endl;
continue;
}
int h;
for(h = 1 ;h <= 10 ; h++ )
{
if(DFS(0,h))
break;
}
if(h == 11)
cout <<"Impossible\n" << endl;
else
{
for(int i = 0 ;i < cnt ;i++)
cout << name[path[i]] << " ";
cout << "\n" << endl;
}
}
return 0;
}