#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int *length, N;
bool *used;
bool cmp(int a, int b) {
return a > b;
}
//if (dfs(N, L, L, -1))
/*R为可供使用的小木棒还有多少个
* M为累加到长度为L的木棒还需要多少长度
* 一开始M肯定是为L的
* 因为最开始的适合还没有添加木块,所以需要的长度为L
* L当前需要的木棒长度
* 最后一次拼接的木棒的下标
* */
bool dfs(int R, int M, int L, int nLastStickNo) {
//全部可用木棒都用完了
//并且拼接为L长度的木棒需要的长度为0
//说明已经拼接好了
//则可以返回true
if (R == 0 && M == 0)
return true;
//一根长度为L的木棒已经拼接好了
// 开始拼接下一根长度为L的木棒
// 更新M的值
//重新赋值为L
if (M == 0)
M = L;
//当前需要的长度不等于L说明
/*已经有木棒在参与构造了
* 则将这个索引加1就可以了
* else
* 则是M等于L
* 说明当前正在构造长度为L的木棒
* 而当前还没有添加木棒上去
* 所以索引应该从0开始遍历
*
* 好像这都像一个顺理成章的条件了
* 并不像一个剪枝
* 既然已经对木棒进行从大到小的排序
* 并且是从最长的木棒开始遍历的长度
* 那么不是就应该是从长选到短*/
M != L ? nLastStickNo += 1 : nLastStickNo = 0;
//从当前索引开始遍历到最大木棒数目
for (int i = nLastStickNo; i < N; i++) {
/*当前遍历木棒没有选择
* 并且当前遍历的木棒的长度小于
* 当前需要的木棒长度
* 则将其选中
* */
if (used[i] == false && length[i] <= M) {
/*如果当前遍历的小木棒不是第一根小木棒
* 并且当前遍历的这跟小木棒前面的那根小木棒没有选择
* 并且当前遍历的小木棒和它前面的那根小木棒长度相等
* 则需要跳过当前遍历的小木棒
* 进入下一根小木棒的选择
* 直接continue*/
if (i > 0 && used[i - 1] == false && length[i] == length[i - 1])
continue;
used[i] = true;
/*选择当前遍历的木棒
* 无法完成拼接
* 即dfs结果返回false
* 则需要取消当前木棒的选择
* 即used[i]赋值为false*/
if (dfs(R - 1, M - length[i], L, i))
return true;
else {
used[i] = false;
/*减法2
* 如果由于以后的拼接失败,需要重新调整当前棍子的拼法,
* 替换掉当前棍子中的第一根小木棒是不行的
*
* 减法3
* 如果当前这根长度未L的棍子拼接成功,但随后的棍子拼接失败,
* 仅替换已拼好棍子的最后一根小木棒是不行的*/
if (M == L || length[i] == M)
return false;
}
}
}
return false;
}
int operation() {
//将录入的小木棒长度从大到小排序
sort(length, length + N, cmp);
int nTotalLen = 0;
//计算录入的小木棒的总长度
for (int i = 0; i < N; i++)
nTotalLen += length[i];
/*计算出木棒总和
* 然后排序
* 然后从最长木棒开始向木棒总和的一半开始遍历
* */
for (int L = length[0]; L <= nTotalLen / 2; L++) {
if (nTotalLen % L == 0) {
// 初始化设置used数组为均为访问
//则全为false
fill(used, used + N, false);
if (dfs(N, L, L, -1))
return L;
}
}
//此时长度已经大于总长度的一半
//所以此时最小的木棒长度就是全部木棒的和
return nTotalLen;
}
int main() {
while (scanf("%d", &N)) {
if (N <= 0)
break;
length = new int[N];
used = new bool[N];
for (int i = 0; i < N; i++)
scanf("%d", &length[i]);
// 打印最短木棒的长度
printf("%d\n", operation());
delete[] used;
delete[] length;
}
return 0;
}
poj1011题解
最新推荐文章于 2022-04-05 20:40:54 发布