P1120 小木棍 [数据加强版]

链接Miku

代码参考:小蓝书

暴力很好写,可惜过不了,怎么办,剪枝起飞。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int len[500001];
int fl[500001];
int sum;
int li;
int cnt;
	int maxx=0;
int ans[500001];
bool dfs(int now,int l,int ord){
	if(now>cnt)//over
	return 1;
	if(l==maxx)
	return dfs(now+1,0,1);//开始下一个 
	int fail=0;
	for(int i=ord;i<=n;++i){
		if(!fl[i]&&l+len[i]<=maxx&&fail!=len[i]){//因为是从大到小放的
		//所以说如果不行的话肯定同样长度的都不行 
			fl[i]=1;
			if(dfs(now,l+len[i],i+1))
			return 1; 
			fail=len[i];
			fl[i]=0;
			//不好理解的剪枝
			//l==0的部分是因为如果此木棍出现在新木棍中不可行的话,那么它出现在之后任何一个新木棍的结果都是一样的--不行
			//后半段同理,贪心的考虑一下,一整根木棍都不行的话,就算用几根小木棍拼起来也没有意义 
			if(l==0||l+len[i]==maxx)
			return 0;
			
		}
	}
	return 0;
}
bool cmp(int x,int y){
	return x>y;
}
int main(){     
		scanf("%d",&n);
		sum=0;
	maxx=0;
	int xiu;
	int lll=0;
		for(int i=1;i<=n;++i){
		scanf("%d",&xiu);
		if(xiu>50)//自动忽略 
		continue;
		len[++lll]=xiu;
		sum+=len[lll];
		maxx=max(maxx,len[lll]);
		}
		n=lll;
		sort(len+1,len+n+1,cmp);
		//从大到小搞啊 
		int i;
		for( ;maxx<=sum;++maxx){
			if(sum%maxx) continue;
			//显然只有原长是总长的因数才有意义 
			cnt=sum/maxx;
			memset(fl,0,sizeof(fl));
			if(dfs(1,0,1)){
			break;
			}
		}
		cout<<maxx<<endl;
	return 0;
}  
posted @   Simex  阅读(121)  评论(0编辑  收藏  举报
编辑推荐:
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
阅读排行:
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· 一个基于 .NET 开源免费的异地组网和内网穿透工具
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
点击右上角即可分享
微信分享提示