数的划分 -- 暴力搜索 审核通过

Horizon 摸鱼 2024-02-28 21:00:54 2024-02-29 13:33:18 27

题意十分直白清晰,直接开搜。

分解范围

要求将数字 n 分成 k 个数,为了预防重复我们可以自己设下规则,即保证分解出来的数字满足以下要求
a1 ⩽ a2 ⩽ a3 ... ... ⩽ ak

极限情况下

a1 = a2 = a3 ... ... = ak

image.png

那么,对于每个分解数的范围就有了要求。

在本例中,如果第一个数字是3,为了保证不会重复,第二个数字也最小为3,第三个数字也最小为3,加和为9,不符合题意。

所以,第一个分解数的范围应该是 1 ~ n/k,第二个开始的分解数都不小于上一个分解数。

阶段划分

分析本例,初识状态为将 7 分解成 3 个数。

在第一步划分出 1 为第一个分解数后,问题规模缩小为,将 (7-1) 分解成 2 个数。

再次分解出 1 为第二个分解数后,问题规模缩小为,将 (7-1-1) 分解成 1 个数。

那么我们也可以由此总结出搜索过程的参数。

pre -- 上一个分解数  k -- 分解个数  sum -- 还剩多少需要分解

边界判定

分解个数为 0 -- k==0

完成分解 -- sum==0

根据前后阶段的分析,可以直接给出搜索函数。

//   上一个分解数pre 分解个数k 剩余待分解数sum
void dfs(int pre, int k, int sum) {
    //已经分解 k 个数 但是没有分解完
    if (k == 0 && sum > 0)
        return;
    //已经分解 k 个数, 且已经分解完
    if (k == 0 && sum == 0) {  
        cnt++;   //计数+1
        return;
    }
    //继续分解, 保证新的分解数大于pre
    for (int i = pre; i <= sum; i++) {
        dfs(i, k - 1, sum - i);
    }
}

分析完核心的搜索函数后,只需要补完主函数即可。

int main() {
    int n, k;  //待分解数 和 分解个数
    cin >> n >> k;
    dfs(1, k, n);  //第一个数字从 1 开始分解
    cout << cnt;
    return 0;
}
{{ vote && vote.total.up }}

共 2 条回复

wczzq 原神启动
root 站长

qp