1. 程式人生 > >洛谷 P1120 小木棍 [資料加強版]

洛谷 P1120 小木棍 [資料加強版]

題目:小木棍

思路:
搜尋+剪枝。
外層迭代加深,列舉最小長度,用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; }