【題解】 洛谷1120 小木棍 [資料加強版]
阿新 • • 發佈:2018-11-05
剪枝好題,可以有以下9個剪枝(基本上都是可行性剪枝,還有一些搜尋順序的剪枝),這是一道除了生日蛋糕以外的剪枝好題當然不會告訴你Biscuit46花了1h做這道題目
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<algorithm> #include<queue> #include<iostream> #include<map> #define ll long long #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout); using namespace std; inline int gi(){ int sum=0,f=1;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return f*sum; } int n,tot,a[70],Max,s,t,L,flag,vis[70],sum[70]; void dfs(int stick,int Length,int last){ if(Length==L){dfs(stick+1,0,1);return;} if(stick==t-1){//Cut3 printf("%d\n",L);exit(0); } for(int i=last;i<=n;i++)//Cut4 if(!vis[i] && a[i]+Length<=L){//Cut5 if(a[i]==a[i-1] && !vis[i-1])continue;//Cut6如果長度相同且上一個沒選,顯然這個也不選。 if(Length+sum[i]<L)return;//Cut7,字尾和優化一下(因為按照從大到小排序) vis[i]=1; dfs(stick,a[i]+Length,i+1); vis[i]=0; if(!Length)return;//Cut8 if(Length+a[i]==L)return;//Cut9 } } bool cmp(int a,int b){ return a>b; } void init(){scanf("%d",&n); for(int i=1;i<=n;i++){ int x;scanf("%d",&x); if(x>50)continue; a[++tot]=x;Max=max(Max,x); s+=x; } sort(a+1,a+n+1,cmp);//Cut1 for(int i=n;i>=1;i--) sum[i]=sum[i+1]+a[i]; n=tot; } int main(){ int i,j,k,m; init(); for(i=Max;i<=s/2;i++){//Cut2,顯然不會選s/2+1~s-1的長度(因為無法湊出) if(s%i!=0)continue; t=s/i;L=i; dfs(0,0,1); } printf("%d\n",s); return 0; }