第七届蓝桥杯大赛个人赛决赛(软件类C语言B组)第二题:凑平方数(深搜)

时间:2022-09-10 09:31:48

凑平方数

把0~9这10个数字,分成多个组,每个组恰好是一个平方数,这是能够办到的。
比如:0, 36, 5948721

再比如:
1098524736
1, 25, 6390784
0, 4, 289, 15376
等等…

注意,0可以作为独立的数字,但不能作为多位数字的开始。
分组时,必须用完所有的数字,不能重复,不能遗漏。

如果不计较小组内数据的先后顺序,请问有多少种不同的分组方案?

注意:需要提交的是一个整数,不要填写多余内容。

【答案】300
【思路分析】我们可以对这10个数字进行全排列,然后再对这十个数字进行划分,划分时对每个数进行判断,然后用map标记一下去重,计算出来结果就好了,具体的分析会在代码中体现。
【正解代码】

#include<iostream>
#include<cstring>
#include<map>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
using namespace std;
#define LL long long

LL sum=0;
int a[10]= {0,1,2,3,4,5,6,7,8,9};
map<string,LL>ma;
LL num[20],num2[20];

void dfs(int cur,int n)
{
if(cur==10)
{
for(int i=0;i<n;i++)//这里为什么要用第二个数组大家思考一下【因为是递归】如果对num数组进行排序,会改变结果,为什么呢?
{
num2[i]=num[i];
}
sort(num2,num2+n);
string str;
for(int i=0; i<n; i++)
{
while(num2[i])
{
int z=num2[i]%10;
num2[i]=num2[i]/10;
char c=z+'0';
str=str+c;
}
str+='*';
}
if(!ma[str])//判重
{
//cout<<str<<endl;
ma[str]++;
sum++;
}
return ;
}
if(a[cur]==0)//如果当前数字为0,直接使用
{
num[n]=0;
dfs(cur+1,n+1);
}
else
{
long long su=0;
for(int i=cur; i<10; i++)
{
su=su*10+a[i];
double ss=sqrt(su);
if(ss==(int)ss)//判断是不是平方数
{
num[n]=su;
dfs(i+1,n+1);
}
}
}
}


int main()
{
sum=0;
ma.clear();
do
{
memset(num,0,sizeof(num));
dfs(0,0);
}
while(next_permutation(a,a+10));
printf("%lld\n",sum);
}