平衡等式 CSUOJ - 2144 (DFS)

猴开森

学了两天第一次不看题解做出一道DFS题,至少看到自己的一点进步,也是很开心了,赶紧把题解写下来

 (o゜▽゜)o☆[BINGO!]


Description

写一个程序要求当输入在整数范围内的一个整数R后, 计算机便会检查,在下式□处能否填上“+”、“-”或“×”号凑成相应等式。如能凑成,则印出所有这些等式的个数。注意,考虑符号的优先级。 1□2□3□4□5□6□7□8□9=R

Input

只有一行,就是一个整数R。

Output

只有一行,就是使等式成立的个数。

Sample Input

20

Sample Output

30

思路

这道题看到之后的初步思路就是枚举所有情况,正是这两天做学的DFS的应用 — 穷举(先探出整个一条路,对这一种情况进行判断,然后继续进行下一种情况的枚举),像这种穷举,普通的循环好像是很难写的(??)反正DFS是可以解决的

WA犯的错误

  • 第一个错误曾经以各种形式犯过,希望以后再也不要这样了,一句一句调试找到的,血的教训:判断一条解是否成立的部分,按照我的方法,是将×后的数先乘到第一个数上,然后将×后的数赋0,这样就可以在之后的加法中直接求和了。但是!!!判断完一次后,我没有重新赋值,因为1-9的存放数组是全局变量,所以下一次的判断是用的被改变的数组进行的,答案当然是错的。总结就是:在使用东西前好好想想它们现在所处的状态,尤其是全局变量
  • 刚开始加减法计算总和的时候,的方法是:首先sum = 1为初值,然后再根据+/-依次将2-9求和!!!但是我忽略了,按照上述的方法,1已经不一定是1了,很可能1是紧接着好多连×,所以sum = a[1] 才对 

核心代码 

void dfs(int cur)
{
	if(cur==9)//8个空,1-8,9的时候说明已经试探出了一种解决方案了,这时才会判断是否可行 
	{ 
		//判断这条解决方案是否成立,成立则total+1
		return; //不论成不成立,这条解决方案处理完了,该下一条了,所以才return 
	}
	for(int i = 1;i<=3;i++)//每个符号空都有3种情况(1+,2-,3*) 
	{
		sign[cur] = i;//这个空试探赋值 
		dfs(cur+1); //为下一个空试探赋值 
	} 	 
}

 

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int sign[10];
int a[11];
long long total;
long long r,sum; 
void dfs(int cur)//cur从1开始 
{
	if(cur==9)
	{
		
		for(int i = 8;i>=1;i--)//先计算乘法 
		{
			if(sign[i]==3) 
			{
				a[i]*=a[i+1];
				a[i+1] = 0;
			}
		 } 
		 sum = a[1];
		 for(int i = 1;i<=8;i++)//求和 
		 {
		 	if(sign[i] == 2) sum-=a[i+1];
		 	else sum+=a[i+1];
		 }
		 for(int i = 1;i<=9;i++) a[i] = i;//之前没想到,每次检测是否成立的时候都将a数组更改后,下次要不重新初始化就做不出来了 
		if(sum==r) total++;
		return;
	}		
	for(int i = 1;i<=3;i++)
	{
		sign[cur] = i;
		dfs(cur+1);		
	}
}
int main(void)
{
	while(scanf("%lld",&r)!=EOF)
	{
		for(int i = 1;i<=9;i++) a[i] = i;
		total = 0;
		dfs(1);
		printf("%lld\n",total);
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39352598/article/details/81261087