蓝桥杯 ALGO-997 粘木棍(dfs)

试题 算法训练 粘木棍

资源限制

时间限制:1.0s 内存限制:256.0MB

问题描述

  有N根木棍,需要将其粘贴成M个长木棍,使得最长的和最短的的差距最小。

输入格式

  第一行两个整数N,M。
  一行N个整数,表示木棍的长度。

输出格式

  一行一个整数,表示最小的差距

样例输入

3 2
10 20 40

样例输出

10

数据规模和约定

N, M<=7


思路:

  1. 合并只需要考虑两个元素的合并,合并后的元素再次加入数组中,等待下次合并

  2. 由n, m知,需要合并的次数为 n - m次,即需要减少的元素个数

  3. 数据最大只有7,dfs+无脑for枚举

  4. dfs 的状态表示的是数组内的剩余元素数量,那么每次合并进入下层,需要u - 1


要点:

  1. 合并两个元素后,删除多余的元素,我的操作是把它和末尾的元素交换,然后进入下层的时候 u - 1,就跟它说拜拜了。回溯只要交换回来,并把合并元素减去它就行
  2. 当某次搜索结束后,选出最大最小值,不使用排序,因为会打乱顺序(复制一份也行,但没必要)

代码:

#include <iostream>
#include <algorithm>

using namespace std;
const int N = 17;
int q[N];
bool st[N];

int n, m, res = 2e9;

void dfs(int u){
    if (u == m){
        int mi = 2e9, ma = -2e9;
        for (int i = 0 ; i < m ; i ++){
            if (q[i] < mi) mi = q[i];
            if (q[i] > ma) ma = q[i];
        }
        res = min(res ,ma - mi);
        return;
    }
    
    for (int i = 0; i < u ; i ++)
        for (int j = i + 1 ; j < u; j ++){
            q[i] += q[j];
            swap(q[j], q[u - 1]);
            dfs(u - 1);
            swap(q[j], q[u - 1]);
            q[i] -= q[j];
        }
}

int main()
{
    cin >> n >> m;
    
    for (int i = 0 ; i < n ; i ++) scanf("%d", &q[i]);
    
    dfs(n);
    
    cout << res << endl;
    
    return 0;
}


吐槽:

简单题,我觉得删除数组元素的这个技巧挺有意思的,删除数组元素就相当于剪枝操作。

posted @ 2022-02-12 14:41  mosqu1to  阅读(768)  评论(0编辑  收藏  举报