2015年清华软院保研机试第2题:找到算式 (dfs)

题目

思路

由于题目里说了不考虑优先级,就是从左向右顺序计算,那就简单多了,直接DFS。因为如果能够得到目标数字要输出算式,所以dfs函数的输出(记作ret)就是一个表示运算符的数,该数的每一个二进制位对应一个运算符,具体来说:

if (ret & (1<<(n-2-i))
{
    oper[i] = '*';
}
else
{
    oper[i] = '+';
}

由于ret取决于深搜的每层运算符的选择,所以这个数同样要作为dfs函数的一个参数输入,每次更新,最后输出。dfs函数的另外两个参数就是日常参数:i表示计算到第几个运算符,cur表示第i个运算符左边的计算结果。

还有就是如果得不到目标数字,要输出所有计算结果中大于目标数字中的最小者。对于这个要求,加一个全局变量表示大于目标数字的最小值就行了,每次如果计算结果大于目标数字,则维护更新该全局变量。

代码

#include<cstdio>

const int INF = 0x3f3f3f3f;
int n, D, minv = INF;
int a[13] = {};

int dfs(int i, int cur, int oper)	// 第i-1个运算符已经放入,当前累积值为cur
	// 用二进制表示运算符,0表示"+", 1表示"*", 例如001表示有++*
	// 如果结果不等于D,返回-1; 否则返回一个数,每一个二进制位代表一个运算符
{
	if (i == n)
	{
		if (cur == D)
		{
			return oper;
		}
		else if (cur > D)
		{
			minv = minv < cur ? minv : cur;
		}
		return -1;
	}
	int ans0 = dfs(i+1, cur + a[i+1], (oper<<1)+0);	// 第i个运算符是加法
	int ans1 = dfs(i+1, cur * a[i+1], (oper<<1)+1);	// 第i个运算符是乘法
	if (ans0 >= 0)
	{
		return ans0;
	}
	else if (ans1 >= 0)
	{
		return ans1; 
	}
	else
	{
		return -1;
	}
}


int main()
{
#ifndef ONLINE_JUDGE
	freopen("thuSE15_02.txt", "r", stdin);
#endif
	int i, ans;
	scanf("%d%d", &n, &D);
	for (i=0; i<n; i++)
	{
		scanf("%d", a+i);
	}
	ans = dfs(0, a[0], 0);
	if (ans >= 0)
	{
		for (i=0; i<n-1; i++)
		{
			printf("%d", a[i]);
			if (ans & (1<<(n-2-i)))
			{
				printf("*");
			}
			else
			{
				printf("+");
			}
		}
		printf("%d", a[n-1]);
	}
	else
	{
		printf("%d", minv);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/82429824
dfs