2016年蓝桥杯决赛-凑平方数

凑平方数

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

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

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

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

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

思路:将所有平方数根据其长度放入不同的组合中,我是用的set来装,然后就是每个位数组合开始遍历;注意每个分组方案中为了防止相同组合不同次序这种情况,所有我们遍历时排一个序,然后就是DFS的事了。说实话这个题调试了很久,原先我一直以为11的倍数一定不是满足条件的,这个主观认识直接导致数据减少了很多。

#include<iostream>
#include<cstdio>
#include<set>
#include<string>
#include<string.h>
using namespace std;
#define ll long long
int flag[10] = { 0 };
set<string>se[11];
ll sum = 0;
bool isOne(string str)
{
    memset(flag, 0, sizeof(flag));
    for (int i = 0; i < str.length(); i++){
        if (str[i] == ' ')continue;
        if (flag[str[i] - '0'] == 0)
            flag[str[i] - '0'] = 1;
        else return false;
    }
    return true;
}
void dfs(int len, int p, ll sp = 9876543210 , string str = "")
{
    //cout << "sp = " << sp << endl;
    if (len == 10){
        if (isOne(str)){
            sum++; 
            printf("%3d : ", sum); cout << str << endl;
        }
        return;
    }
    
    for (int i = p; i >=1; i--){
        set<string>::iterator iter;
        for (iter = se[i].begin(); iter != se[i].end(); iter++){
            ll temp = atoi((*iter).c_str());
            if (temp >= sp)break;
            
            
            if (isOne(str + *iter)){
                //cout << " len = " << len << " " << sp << " ?= " << *iter << endl;
                dfs(len + i, i, temp, str + " " + *iter);
            }
        }
    }
}
int main()
{
    
    for (ll i = 0; i*i <= 9876543210; i++){
        string temp = to_string(i*i);
        
        if (isOne(temp)){
            int cnt = temp.length();
            se[cnt].insert(temp);
        }
    }
    dfs(0, 10);
    cout << "sum = " << sum << endl;
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zengguoqiang/p/9057370.html