算法提高之木棒
-
核心思想:dfs + 剪枝优化
- 1.搜索顺序优化:len从小到大遍历
- 2**.剪枝(失败后):**
- (1) 跳过所有和第i根木棍相同长度的木棍
- (2) 如果当前木棍是新木棒的第一根就失败了 则之后不会搜到方案 return false
- (3) 下一根失败但是上一根成功(cur+w[i]==len) 之后也不会有方案 直接return false
-
#include<iostream>#include<cstring>#include<algorithm>using namespace std;const int N = 70;int n;bool st[N];int w[N];int sum,len;bool dfs(int u,int cur,int start) //u为长木棍数量 cur为当前长木棍长度 start为当前木棍编号{if(u * len == sum) return true; //全部拼出来if(cur == len) return dfs(u+1,0,0); //当前这根拼完for(int i=start;i<n;i++){if(st[i]) continue; //被搜过if(cur+w[i] <= len){st[i] = true;if(dfs(u,cur+w[i],i+1)) return true;st[i] = false; //恢复现场}//失败后if(!cur || cur + w[i] == len) return false; //2 3剪枝int j = i+1;while(j<n && w[i] == w[j]) j++; //1剪枝i = j-1;}return false;}int main(){while(cin>>n , n){sum = len = 0;for(int i=0;i<n;i++){cin>>w[i];sum += w[i];len = max(len,w[i]); //取最长木棍}sort(w,w+n,greater<int>());memset(st,0,sizeof st);while(true){if(sum % len == 0 && dfs(0,0,0)) //len从最长小木棍开始++{cout<<len<<endl;break;}len++;}}return 0;}