E- Seven tombs
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 31 Accepted Submission(s) : 9
Problem Description
塔.拉夏被埋葬在术士峡谷的七个古墓中的一个。
塔.拉夏的古墓一共有七种不同的符号,分别用A、B、C、D、E、F、G表示。每个古墓中分别封印着一种力量,用1、2、3、4、5、6、7表示。为了防止以后有人取得这些力量,赫拉迪姆将这些对应的关系全部隐藏起来了。
为了获得这七种力量,你终于找到了一点线索:一个古代赫拉迪姆留下的式子。这个式子表示了七种力量对应的关系。经过破译,终于知道将七种符号所表示的力量的代号分别代进式子中,使得等式成立的,就是开启封印的钥匙。
写一个程序解开这个迷题。
Input
一行一个字符串,为一个只有变量A..G的等式。式子中只含有字母、加、减、乘号以及括号和一个等号,并且“ABC”表示A*100+B*10+C,字符串长度不超过100。
Output
一行,输出对应等式的解。如果有多种可能,输出ABCDEFG表示十进制数最小的一个。输入数据保证有解。
Sample Input
Sample Output
Author
hnfnu
表达式树是一棵神奇的树。。参考资料:刘汝佳著《算法竞赛入门经典》P197页
核心思想就是去找表达式中最后运算的运算符。
样例建树结果为:(等式左边)
绿色为U值
next_permutation(str,str+n);输出str按字典序的下一位
//Tine: 0 MS
//Memory: 496 KB
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=200;
int lch[2][maxn],rch[2][maxn];
vector<char>op[2][maxn];//每个节点的左右儿子编号和字符
int nc=0;//节点数
int f[7]={1,2,3,4,5,6,7};
int build_tree(char *s,int x,int y,int t)
{
int i,c1=-1,c2=-1,p=0;
int u;
for(i=x;i<y;i++)
if(s[i]<'A' || s[i]>'G')
break;
if(i==y)//此处仅剩字符,没有运算符了
{
u=++nc;
lch[t][u]=rch[t][u]=0;
for(i=x;i<y;i++)
op[t][u].push_back(s[i]);
return u;
}
for(i=x;i<y;i++)
{
switch(s[i])
{
case '(':p++;break;
case ')':p--;break;
case '+':case '-':if(!p) c1=i;break;
case '*':case '/':if(!p) c2=i;break;
}
}
if(c1<0)//没有括号外的加减号,则用乘除号
c1=c2;
if(c1<0)
return build_tree(s,x+1,y-1,t);//此情况就是表达式被括号括住
u=++nc;
lch[t][u]=build_tree(s,x,c1,t);
rch[t][u]=build_tree(s,c1+1,y,t);
op[t][u].push_back(s[c1]);
return u;
}
int num(int u,int t)
{
int temp=1,sum=0,i;
if(op[t][u][0]=='+')
return num(lch[t][u],t)+num(rch[t][u],t);
else if(op[t][u][0]=='-')
return num(lch[t][u],t)-num(rch[t][u],t);
else if(op[t][u][0]=='*')
return num(lch[t][u],t)*num(rch[t][u],t);
else
{
for(i=op[t][u].size()-1;i>=0;i--)
{
sum+=temp*f[ op[t][u][i]-'A' ];
temp*=10;
}
return sum;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
char s[200],s1[200],s2[200];
int i,j;
while(scanf("%s",s)!=EOF)
{
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
int l=strlen(s);
int l1=0,l2=0;
bool flag=true;
for(i=0;i<l;i++)
{
if(!flag)
s2[l2++]=s[i];
if(s[i]=='=')
flag=false;
if(flag)
s1[l1++]=s[i];
}
nc=0;
int node1=build_tree(s1,0,l1,0);
nc=0;
int node2=build_tree(s2,0,l2,1);
for(i=0;i<7;i++)
f[i]=i+1;
int lsum,rsum;
do
{
lsum=num(node1,0);
rsum=num(node2,1);
if(lsum==rsum)
break;
}while(next_permutation(f,f+7));
for(i=0;i<l;i++)
{
if(s[i]>='A' && s[i]<='G')
printf("%d",f[s[i]-'A']);
else
printf("%c",s[i]);
}
printf("\n");
}
return 0;
}