题意:给定一个集合,若集合中任意n个元素相加的和仍属于集合,则输出这个等式
思路:由于按等式的长度进行输出,所以按照相应的长度选择dfs搜索的深度,找出合适的解
代码:这里的1和2代表不同的选择(并没有什么区别),只是需要十分注意这些边界问题,
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int a[50],vis[50];
int flag=0;
void dfs(int num,int len,int sum) //num 当前的位置 len 算式的长度, sum 算式的和
{
if(len==0)//限制搜索深度
{
//for(int i=num+1;i<n;i++) //1
for(int i=num;i<n;i++) //2
{
if(sum==a[i])//和是否属于集合
{
flag=1;
for(int j=0;j<i;j++)
{
if(vis[j])
{
if(sum==a[j])
printf("%d=%d\n",a[j],a[i]);//通过逐步相减,当两者相同时,即为最后一个加数
else
{
printf("%d+",a[j]);
sum-=a[j];
}
}
}
}
else if(sum<a[i])
break;
}
}
else
{
//for(int i=num+1;i<n;i++) //1
for(int i=num;i<n;i++) //2
{
if(sum+a[i]<=a[n-1])
{
vis[i]=1;
sum+=a[i];
len--;
//dfs(i,len,sum);// 注意这里num的选择 1
dfs(i+1,len,sum); //2
vis[i]=0; // 这里因为要找所有的解,不能通过判断flag直接返回
sum-=a[i];
len++;
}
}
}
}
int main()
{
int t;
//freopen("in.txt","r",stdin);
scanf("%d",&t);
while(t--)
{
flag=0;
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
int sum=0;
sort(a, a+n);
for(int i=2;i<n;i++)
{
//dfs(-1,i,0); //1
dfs(0,i,0); //2
}
if(!flag)
printf("Can't find any equations.\n");
printf("\n");
}
}