UVA_307
相当于重温了一下POJ 1011这个题目,剪枝在这个题目中显得尤为重要。
对于这道题而言,剪枝的策略一般有下面6个:
①先将木棒长度从大到小进行排序,这样便于后面的选择和操作,是后面一些剪枝算法的前提。
②在枚举原木棒长度时,枚举的范围为max与sum/2之间,如果这个区间内没有找到合适的长度,那么最后原木棒的长度只能是sum。
③枚举的原木棒的长度只能是sum的约数。
④在深搜过程中,如果当前木棒和前一个木棒的长度是一样的,但是前一个木棒没有被选上,那么这个木棒也一定不会被选上。
⑤在深搜过程中,如果当前是在拼一根新木棒的第一截,但如果把可用的最长的一根木棒用上后不能拼成功的话,那么就不用再试后面的木棒了,肯定是前面拼的过程出了问题。
⑥在深搜过程中,如果当前可用的木棒恰好能补上一根原木棒的最后一截,但用它补上之后却不能用剩下的木棒完成后续的任务,那么也不用再试后面的木棒了,肯定是前面拼的过程出了问题。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int sum,N,n,L,a[100],vis[100];
int cmp(const void *_p,const void *_q)
{
int *p=(int *)_p;
int *q=(int *)_q;
return *q-*p;
}
int dfs(cur,complete,len)
{
int i;
if(len==L)
{
complete++;
if(complete==N)
return 1;
else
{
for(cur=0;vis[cur];cur++);
vis[cur]=1;
if(dfs(cur+1,complete,a[cur]))
return 1;
vis[cur]=0;
}
}
else
{
for(i=cur;i<n;i++)
if(!vis[i]&&a[i]<=L-len)
{
if(i!=0&&a[i]==a[i-1]&&!vis[i-1])
continue;
vis[i]=1;
if(dfs(i+1,complete,len+a[i]))
return 1;
vis[i]=0;
if(a[i]==L-len)
return 0;
}
}
return 0;
}
int main()
{
int i,j,k,max;
while(1)
{
scanf("%d",&n);
if(n==0)
break;
sum=max=0;
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]>max)
max=a[i];
sum+=a[i];
}
qsort(a,n,sizeof(a[0]),cmp);
memset(vis,0,sizeof(vis));
for(L=max;L<=sum/2;L++)
{
if(sum%L!=0)
continue;
N=sum/L;
if(dfs(0,0,0))
break;
}
if(L>sum/2)
printf("%d\n",sum);
else
printf("%d\n",L);
}
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 2025成都.NET开发者Connect圆满结束
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络