#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int N, L;//棒子数,棍子长度
vector<int> anLength;//每一根棒子的长度
int anUsed[65];//用过标记
int i, j, k,anLastTickNo=0;
bool Dfs(int R, int M);
int main() {
while (1) {
cout << "输入棒子总数:";
cin >> N;
if (N == 0) break;
int nTotalLen = 0;//棒子总长度
anLength.clear();
cout << endl;
cout << "输入"<<N<<"根棒子的长度:";
for (int i = 0; i < N; i++) {//输入棒子长度
int n;
cin >> n;
anLength.push_back(n);
nTotalLen += anLength[i];
}
sort(anLength.begin(), anLength.end(), greater<int>());
for (L = anLength[0]; L <= nTotalLen / 2; L++) {//枚举棍子长度
if (nTotalLen % L)
continue;
memset(anUsed, 0, sizeof(anUsed));//标记置0
if (Dfs(N, L)) {
cout << "最短的棍子长度是:" << L << endl;
break;
}
}
if (L > nTotalLen / 2)
cout << "没有找到合适的棍子长度." << endl;
break;
}
return 0;
}
bool Dfs(int R, int M) {
if (R == 0 && M == 0) return true;
if (M == 0)//一根已拼好,拼下一根
M = L;
int anStart = 0;
if (!M == L) anStart = anLastTickNo + 1;//不是棍子的第一根棒子时,从下一根短的棒子开始试
for (int i = anStart; i < N; i++) {
if (!anUsed[i] && anLength[i] <= M) {//i木棒没有使用,长度短于M
if (i > 0) {//不是第一根木棒
if (anUsed[i - 1] = false && anLength[i] == anLength[i - 1])//前一根没用上,这根长度和上一根长度一样,剪枝
continue;
}
anUsed[i] = 1;//符合条件使用这根棒子
anLastTickNo = i;//当前使用的棒子
if (Dfs(R - 1, M - anLength[i]))
return true;
else {
anUsed[i] = 0;//不合适,拆掉这根棒子
if (M == L || anLength[i] == M) return false;//是棍子的第一根和最后一根木棒,放弃后面的尝试
}
}
}
return false;
}
北大 算法基础 深搜之拯救少林神棍
最新推荐文章于 2024-11-06 11:05:01 发布