ZOJ 1204 Additive equations

原题链接

题目大意:给出一列数据,不多于30个。如果其中的两个或多个数之和等于这组数据中的另一个数,如{1,2,3}这个数组中存在等式1+2=3,输出这个等式。找出满足条件的所有等式。如果,找不到符合条件的,输出“Can’t find any equations.”。

解法:把这个数组的所有数字排序。首先,从小到大开始累加数字,直到和超过数组的最大值,这样我们可以知道,等式左边最多可以有几个数字。然后,从两个加数开始,用深度优先的方法,从左往右搜索,寻找是否存在满足条件的等式。依次递增搜索的深度。

参考代码:

//参考了这篇日志http://blog.csdn.net/scnu_jiechao/article/details/8134952
#include<iostream>
#include<algorithm>
using namespace std;

int M[32],C[32],n,visited[32],flag;
//cur 表示当前使用数字的个数,dest表示这一轮需要的加数个数,temp表示当前和,last表示前一个加数的下标
void dfs(int cur,int dest, int temp, int last);
//检查能否在数组中找到对应的求和数
int exist(int last, int n, int tsum);
int main(){
	int cases,i,j,m,deep;

	cin>>cases;
	while(cases--){
		cin>>n;
		for(i=0;i<n;i++)
			cin>>M[i];
		sort(M,M+n);  //输入数字不一定按照顺序,要先排序
		int sum=0;
		i=0;
		while(sum<=M[n-1]) sum+=M[i++];
		deep=i-1;
		flag=0; 
		for(i=2;i<=deep;i++){
			dfs(0,i,0,0);
		}
		if(!flag) cout<<"Can't find any equations."<<endl;
		cout<<endl;
	}
	return 0;
}

void dfs(int cur,int dest, int tsum, int last){
	
	if(cur==dest){  //等号左边数的个数等于本轮搜索的加数个数
		if(exist(last,n,tsum)){  //能否找到一个数等于当前和,找到就输出,找不到就放弃;
			for(int i=0;i<dest-1;i++)
				cout<<C[i]<<"+";  //C数组暂时保存前面的加数
			cout<<C[dest-1]<<"="<<tsum<<endl;
			flag=1;
		}
	}
	else{
		for(int i=last;i<n;i++){ //如果加数数目不够,在余下的数里寻找
			if(tsum+M[i]<=M[n-1]&&C[cur-1]!=M[i]){  
				C[cur]=M[i];   //当前数字入栈
				dfs(cur+1,dest,tsum+M[i],i);
			}
		}
	}
}

int exist(int x, int y, int v){
	int m;
	while(x < y)  
    {  
        m = x + (y-x)/2;  //用二分法来找等式右边的数字
        if(M[m] == v) return 1;  
        else if(M[m] > v) y = m;  
        else x = m + 1;  
    }  
    return 0;  

}
原文地址:https://www.cnblogs.com/naive/p/3568807.html