这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
题目的大致意思是,告知一开始有若干木棍的长度相等的木棍,然后把他们切成n个不同长度的小木棍,这n个不同长度的小木棍的长度已知,要你求最开始的木棍长度最小可以为多少。
二、题目思路以及AC代码
这题一开始看到的思路也很清晰,就是,首先,由于一开始木棍长度都相等,所以这个长度必定是给定的n个长度和的一个因子,然后解决方法就是对每个因子进行遍历,然后每次遍历求解一次dfs,看是否可以达到这个长度,因为因子是从小到大排列,所以找最先找到的那个就可以了。
但是思路是思路,AC是AC,这题要想AC,可远没有思路这么简单,需要进行剪枝。主要就是两部分剪枝。
- 不要重复dfs相同长度的木块,在找寻一个目标长度的木块时,如果已经发现长度为x的不能使结果成立,那么就不要再用这个长度了。
- 如果在新凑一个目标长度的木块时,此时第一个长度的木块不能使目标成立,那么直接返回不可能即可。(因为假设你已经凑好了2个木块,刚要凑第三个,然后你取到sticks[i],发现后面的木块任意组合也无法满足要求,那么这种方法就是不可能的,直接返回false即可,如果不返回false,你就会将这一块的下一块作为第三块的第一个,这时已经不可能成立了,因为你要凑的是若干个完整的木块,对于每个小木板的地位是相同的,这个不行,其他的肯定也不可以,如果你要问为什么是第一块,那么我的解释是,如果你中间的某块发现后面任意组合也不行,那你换一块,说不定就可以把当前这个大木块满足,然后后面也可能会满足。尽量去理解吧,确实有点难)
然后其实就没有了,这样,就可以把一个原本TLE的暴力dfs,变成一个20ms的AC代码。
下面给出AC代码:
#include <iostream>
#include <algorithm>
#define MAXN 70
using namespace std;
int n;
int sticks[MAXN];
int vis[MAXN];
int factor[30];
int fsize;
int cnt = 0;
void init() {
for (int i=0;i<MAXN;i++){
sticks[i] = 0;
vis[i] = false;
}
for (int i = 0; i < 30; i++) {
factor[i] = 0;
}
fsize = 0;
cnt = 0;
}
bool allVis() {
for (int i = 0; i < n; i++) {
if (!vis[i]) return false;
}
return true;
}
bool dfs(int cur, int m, int pre, int num) {
if (cur == m) {
if (num == n) return true;
if (dfs(0, m, 0, num)) return true;
return false;
}
else if (cur > m) return false;
for (int i = pre; i < n; i++) {
if (vis[i]) continue;
if (sticks[i] > m - cur) continue;
if (i > 0 && !vis[i - 1] && sticks[i - 1] == sticks[i]) continue;
vis[i] = true;
if (dfs(cur + sticks[i], m, i + 1, num + 1))
return true;
vis[i] = false;
if (pre == 0)
return false;
}
return false;
}
bool cmp(int a, int b) {
return a > b;
}
int main()
{
while (cin >> n) {
if (!n) break;
init();
int max = -1;
int sum = 0;
for (int i = 0; i < n; i++) {
cin >> sticks[i];
sum += sticks[i];
if (max < sticks[i])
max = sticks[i];
}
sort(sticks, sticks + n, cmp);
for (int i = 1; i <= sum; i++) {
if (sum % i == 0) factor[fsize++] = i;
}
int idx = 0;
for (int i = 0; i < fsize; i++) {
if (factor[i] >= max) {
idx = i;
break;
}
}
while (idx < fsize && !dfs(0, factor[idx], 0, 0)) {
idx++;
}
cout << factor[idx] << endl;
}
return 0;
}
如果有问题,欢迎大家指正!!!