Seven tombs (表达式树)

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

(A+B)*C-E*(C+D)=FF

Sample Output

(2+6)*7-1*(7+5)=44

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;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值