算m点问题(dfs+排列树)

题目描述:给定k个正整数,用算术运算符+,-,*,/将这k个正整数链接起来,使最终的得数恰为m。
如果有多组满足要求的表达式,只要输出一组,每一步算式用分号隔开。如果无法得到m,则输出"No Solution"


样例输入:

5 125

7 2 2 12 3

样例输出:

7 * 3 = 21; 21 * 12 = 252 ; 252 - 2 = 250; 250 / 2 = 125


排列树

tips:关键是如何在搜索的过程中,逐步输出表达式。
这里的思路是:
如果最后得到了m的值,则返回true,否则返回false.并且回溯过程中(输出表达式的信息)每一步同样都返回true.
否则一律返回false.


代码如下:


#include<string>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<fstream> 
using namespace std;

int a[10001];
int book[10001];//标记a数组i下表的数字是否使用过 
int n;//正整数的个数
int m;//待求得数字
int flag;//题目要求只输出一组解,用于标记是否找到了一组可行解 
ifstream input("input.txt");
ofstream output("output.txt");

//表示搜索到第step层,并且前step-1层算式的值是value 
bool dfs(int  step, int value)
{
	//剪枝:如果已经找到一组可行解,不再进行搜索 
	if (flag)return false;

	//搜索到第n+1层 
	if (step == n + 1)
	{
		//如果满足题目要求 
		if (value == m)
		{
			flag = 1;
			return true;
		}
		//否则返回false 
		else return false;
	}

	for (int i = 1; i <= n; i++)
	{
		//如果下表为i的数字没有使用过 
		if (!book[i])
		{
			//标记
			book[i] = 1;

			//搜索下一层 
			if (dfs(step + 1, value + a[i]))
			{
				//回溯输出,只有当满足题意返回值为true时才进行输出,否则不输出 
				if (step != 1)
				{
					cout << value << "+" << a[i] << "=" << value + a[i] << ";";//<< endl;
					output << value << "+" << a[i] << "=" << value + a[i] << ";";
				}


				return true;
			}
			if (dfs(step + 1, value - a[i]))
			{
				if (step != 1)
				{
					cout << value << "-" << a[i] << "=" << value - a[i] << ";";//<< endl;
					output << value << "-" << a[i] << "=" << value - a[i] << ";";
				}

				return true;
			}
			if (dfs(step + 1, value * a[i]))
			{
				if (step != 1)
				{
					cout << value << "*" << a[i] << "=" << value * a[i] << ";";//<< endl;
					output << value << "*" << a[i] << "=" << value * a[i] << ";";//<< endl;
				}

				return true;
			}
			if (dfs(step + 1, value / a[i]))
			{
				if (step != 1)
				{
					cout << value << "/" << a[i] << "=" << value / a[i] << ";";//<< endl;
					output << value << "/" << a[i] << "=" << value / a[i] << ";";//<< endl;
				}
				return true;
			}
			//回溯,标记清零 
			book[i] = 0;
		}
	}
	return false;

}

int main()
{

	input >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		input >> a[i];
	}

	dfs(1, 0);

	//如果没有找到一组解 
	if (!flag)
	{
		cout << "No Solution" << endl;
		output << "No Solution" << endl;
	}

	return 0;
}


  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值