【题解】 洛谷1120 小木棍 [数据加强版]

原题


剪枝好题,可以有以下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;
}
posted @ 2018-11-05 15:03  cjgjh  阅读(136)  评论(0编辑  收藏  举报