木棒

木棒

给出n件物品,第i件物品的质量为(c_i),询问分成的一些,保证每组物品的质量之和相等,使每组物品质量之和尽可能下,其中(nleq 64,c_ileq 50)

数据范围很小,可以考虑搜索,以下给出优化过程。

  1. 显然当每组质量(s)相等,设所有物品的总质量为(sum),那么s必然为(sum)的约数,于是我们只要从小到大枚举s为sum的约数即可,而且记最大的物品质量为(mx),那么s必然大于等于(mx)

  2. 搜索框架为每一组放哪些物品,不选择每件物品放哪些组的原因在于,不好判断质量之和是否相等。

  3. 显然可以最优性剪枝,当当前搜索状态对应的答案大于等于已经搜出的答案,可以return

  4. 显然可以改变搜索顺序,先搜索质量大的物品。

  5. 显然可以进行去重,首先每一组的物品放入顺序编号递增

  6. 显然可以去重,对于质量相同的物品,当其中一件失败了,其他没必要尝试

  7. 当放入一组的第一件物品,如果他失败了,后面的必然失败,return掉.

  8. 当放入一组的最后一件物品,如果他失败了,后面放入的物品情况被前者包含,因此没必要尝试,return掉。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
using namespace std;
bool v[100];
int n,len[100],sum,
	mx,gt,gn;
il void read(int&);
bool dfs(int,int,int);
int main(){
	while(read(n),n){sum=mx=gt=0;
		for(int i(1);i<=n;++i){read(gn);
			if(gn<=50)sum+=gn,mx=max(gn,mx),
						  len[++gt]=gn;
		}n=gt,memset(v,0,sizeof(v));
		sort(len+1,len+n+1,greater<int>());
		for(int i(mx);i<=sum;++i){
			if(sum%i)continue;gt=i,gn=sum/i;
			if(dfs(1,0,0)){
				printf("%d
",i);break;
			}
		}
	}
	return 0;
}
bool dfs(int a,int last,int cnt){
	if(a>gn)return true;
	if(cnt==gt)return dfs(a+1,0,0);
	int fail(0);
	for(int i(last+1);i<=n;++i){
		if(v[i]||len[i]+cnt>gt||fail==len[i])continue;
		v[i]|=true;if(dfs(a,i,cnt+len[i]))return true;
		v[i]&=false,fail=len[i];if(cnt+len[i]==gt||!cnt)
									return false;
	}return false;
}
il void read(int &x){
	x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

原文地址:https://www.cnblogs.com/a1b3c7d9/p/11276273.html