洛谷 P1120 小木棍 [資料加強版]
阿新 • • 發佈:2018-12-24
題目:小木棍
思路:
搜尋+剪枝。
外層迭代加深,列舉最小長度,用dfs判斷。
dfs維護3個變數x,y,lst,即用了x根木棍,當前拼到了y,上一根木棍的長度為lst。
然後列舉拼接的木棍就好。
剪枝一:從大到小排序。
剪枝二:如果y不為0,那麼列舉的木棍長不要大於lst,不然就會重複搜尋。
剪枝三:如果y==0且列舉的當前木棍不可行那麼就不用再往後列舉。
剪枝四:如果 y+當前木棍長 == 列舉的mid ,且當前木棍不可行,可直接return false。
剪枝五:相同長度的木棍在同一層只用考慮一根就好。
程式碼:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define maxn 65
#define read(x) scanf("%d",&x)
int n,m;
int a[maxn+5];
int mid;
bool use[maxn+5];
bool dfs(int x,int y,int lst) {
if(y==0&&n==x-1) return true;
if(n==x-1) return false;
for(int i=1;i<=n;i++) {
if(use[i]||a[i]+y>mid||(a[i]>lst&& y!=0)) continue;
use[i]=true;
if(dfs(x+1,y+a[i]==mid?0:y+a[i],a[i])) return true;
use[i]=false;
if(y==0||a[i]+y==mid) return false;
while(a[i+1]==a[i]) i++;
}
return false ;
}
bool cmp(const int& x,const int& y) {
return x>y;
}
int main() {
read(n);
for(int i=1;i<=n;i++) {
read(a[i]);
if(a[i]>50) n--,i--;
else m+=a[i];
}
sort(a+1,a+n+1,cmp);
for(mid=a[1];mid<=m;mid++) {
if(m%mid) continue;
memset(use,0,sizeof(use));
if(dfs(1,0,mid)) break;
}
printf("%d",mid);
return 0;
}