HDU 4192 Guess the Numbers (表达式)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4192

题目的意思就是先给出n个数据,在给出一个结果m,在给你一个含有n个变量的表达式,问是否存在一种方式将数据一一代入变量,使得表达式的结果等于m。

解题思路:由于n不大,所以可以暴力求出这n个数的所有组合方式,然后求出结果看是不是等于m,得到组合后就可以替换变量得到一个不含未知数的中缀表达式,就可求出结果,这题用了以前的先建树在求解的模板,一直超时,后来改了,直接以建树的方式求解,就过了,参考代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<cstdlib>
using namespace std;

#define MAX 105
#define CLR(arr) memset(arr,0,sizeof(arr))

char str[MAX]; //中序表达式
int num[10],vis[10],res[10]; /*num[]存入初始数据,res[]存入组合方式(存的是下标),*/
char strr[MAX],str1[MAX],ch[10],s[10][10]; 
/*strr数组转化后的表达式,str1含未知数的表达式,s为给出的几个数据用字符串存起来*/ 

int creat(int b,int e)
{
	if(b > e) return 0;
	int p = -1,cnt = 0,flag = 0;
	for(int i = b;i <= e;++i)
	{
		if(str[i] == '(')      cnt++;
		else if(str[i] == ')') cnt--;
		else if((str[i] == '+' || str[i] == '-') && !cnt){flag = 1; p = i;}
		else if((str[i] == '*' || str[i] == '/') && !cnt && !flag)  p = i;
	}
	if(p == -1) 
	{
		if(str[b] <= '9' && str[b] >= '0')
		{
			int res = 0; int n = 0;
			sscanf(&str[b],"%d%n",&res,&n);
			return res;
		}
		return creat(b+1,e-1);
	}
	else 
	{
		switch(str[p])
		{
		case '+':return creat(b,p - 1) + creat(p + 1,e);
		case '-':return creat(b,p - 1) - creat(p + 1,e);
		case '*':return creat(b,p - 1) * creat(p + 1,e);
		default: break;
		}
	}
}

int EXP(char st[])
{
	strcpy(str,st);
	return creat(0,strlen(str)-1); //中序求出结果
}

bool dfs(int p,int n,int m)  //深搜考虑每一种情况
{
	if(p == n)
	{
		CLR(strr);
		int pos = 0;
		for(int i = 0;i < strlen(str1);++i)
		{
			if(str1[i] <= 'z' && str1[i] >= 'a')
				strcat(strr,s[ res[pos++] ]); 
			else
			{
				ch[0] = str1[i];
				ch[1] = '\0';
				strcat(strr,ch);
			}
		}
		int a = EXP(strr);
		if(a == m) return true;
		else return false;
	}
	for(int i = 0;i < n;++i)
	{
		if(!vis[i])
		{
			vis[i] = true;
			res[p] = i;
			if(dfs(p+1,n,m)) return true;
			vis[i] = false;
		}
	}
	return false;
}

int main()
{
	int m,n;
	char cha[10];
	while(~scanf("%d",&n))
	{
		if(!n) return 0;
		CLR(str1); CLR(res);
		CLR(num); CLR(vis);
		int pos,r;
		for(int i = 0;i < n;++i)
		{
			scanf("%d",&num[i]);
			CLR(ch); CLR(cha);
			pos = 0; 
			r = num[i];
			/****数字转换为字符串*****/
			if(!r) cha[pos++] = '0';
			while(r)
			{
				cha[pos++] = '0' + (r % 10);
				r /= 10;
			}
			for(int j = 0;j < pos;++j)
				ch[j] = cha[pos-1-j];
			ch[pos] = '\0';
			strcpy(s[i],ch);
			/*****************/
		}
		scanf("%d",&m);
		scanf("%s",str1);
		if(dfs(0,n,m)) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值