【回溯】B029_LQ_凑平方数(记录状态新写法)

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

比如:0,36,5948721

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

注意,0 可以作为独立的数字,但不能作为多位数字的开始。

分组时,必须用完所有的数字,不能重复,不能遗漏。

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

方法一:回溯

思路

dfs 需要记录什么?

  • 组的长度(当前组内数组的总长),即为 len
  • 由于组内是不计较循序且不能有重复数,为了加快速度,我规定了从小到大排列组内的完全平方数

候选的完全平方数 next 应满足:next 本身没有重复数,且与历史中被选中的完全平方数没有重叠数字

#include
using namespace std;

int ans, vis[10];
int get_len(long num) {
    // if (num==0) return 1;
    // int n=0;
    // while (num) {
    //     num/=10, n++;
    // }
    // return n;
}
void change_state(long num) {
    if (num==0) {vis[0]^=1; return;}
    while (num) {
        vis[num%10]^=1;
        num/=10;
    }
}
bool chk(long num) {
    if (num==0) return !vis[num];
    vector<bool> st(10, false);
    while (num) {
        int dig=num%10;
        if (vis[dig] || st[dig]) return false;
        st[dig]=1;
        num/=10;
    }
    return true;
}
void dfs(int len, long last) {
    if (len==10) {
        ans++;
        return;
    }    
    for (long i=last+1; i<=100000; i++) {
        long next=i*i;
        if (chk(next)) {
            change_state(next);
            dfs(len+get_len(next), i);
            change_state(next);
        } 
    }
}
int main() {
    std::ios::sync_with_stdio(false);
    memset(vis, 0, sizeof vis);
    dfs(0, -1);
    cout << ans;
    return 0;
}

你可能感兴趣的:(#,【回溯】)