蓝桥杯 ALGO-997 粘木棍(dfs)
试题 算法训练 粘木棍
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
有N根木棍,需要将其粘贴成M个长木棍,使得最长的和最短的的差距最小。
输入格式
第一行两个整数N,M。
一行N个整数,表示木棍的长度。
输出格式
一行一个整数,表示最小的差距
样例输入
3 2
10 20 40
样例输出
10
数据规模和约定
N, M<=7
思路:
-
合并只需要考虑两个元素的合并,合并后的元素再次加入数组中,等待下次合并
-
由n, m知,需要合并的次数为
n - m
次,即需要减少的元素个数 -
数据最大只有7,dfs+无脑for枚举
-
dfs 的状态表示的是数组内的剩余元素数量,那么每次合并进入下层,需要
u - 1
要点:
- 合并两个元素后,删除多余的元素,我的操作是把它和末尾的元素交换,然后进入下层的时候
u - 1
,就跟它说拜拜了。回溯只要交换回来,并把合并元素减去它就行 - 当某次搜索结束后,选出最大最小值,不使用排序,因为会打乱顺序(复制一份也行,但没必要)
代码:
#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;
}
![](https://img2022.cnblogs.com/blog/2675100/202202/2675100-20220212144009274-1096825309.png)
吐槽:
简单题,我觉得删除数组元素的这个技巧挺有意思的,删除数组元素就相当于剪枝操作。