点此看题面

大致题意: 给你\(N\)根小木棍,请你把它们拼成若干根长度相同的木棍,问你最小可能长度。

枚举+\(dfs\)

显然的,木棍的长度肯定是\(\sum_{i=1}^n len[i]\)的一个因数,且肯定大于\(max(len[i])\)。因此,我们只要在这个范围内枚举答案并用\(dfs\)来验证即可。

另外,只要找到一个答案,我们就可以立刻结束程序了(这应该是显然的)。

这样不就好了吗?

等等,一个裸的暴搜显然是卡不过去的(如果能过当我没说),必须要加上大量的剪枝才可以。

一大波剪枝

这道题木棍的长度在\(50\)以内,所以显然我们可以用桶来存储。

我们可以从大到小来枚举每一个长度,只要当前长度加上已经拼接好的木棍的长度不会超过当前所要验证的长度,我们就对其进行\(dfs\)。

还有一个小优化就是,在每一次\(dfs\)结束后,若原先并没有已经拼接好的木棍,或者已经拼接好的木棍的长度加上当前长度恰好等于当前所要验证的长度,我们就立刻结束枚举,因为这根木棍肯定是要选的,这两种情况下选了肯定比不选状态更优。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define N 65
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,maxx=0,minn=1e9,a[N+5];
inline void read(int &x)
{
x=0;char ch;
while(!isdigit(ch=tc()));
while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
}
inline void write(int x)
{
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline void dfs(int x,int Min,int v,int ans)//用dfs来验证一个答案是否可行
{
if(!x) {write(ans),fwrite(pp,1,pp_,stdin);exit(0);}//如果可行,就直接输出答案,结束程序
if(v==ans) {dfs(x-1,maxx,0,ans);return;}//如果当前木棍的长度刚好为要验证的长度,说明拼好了一根木棍,就将剩余要拼接的木棍的根数减1,并可以重新从最大的开始枚举了
if(ans-v<minn) return;//如果当前已拼好的木棍的长度加上最短的一根木棍的长度都比要验证的木棍长度大,就说明不可行,退出函数
for(register int i=Min;i>=minn;--i)//从上一次使用的木棍长度开始从大到小枚举木棍长度
{
if(v+i<=ans&&a[i])//如果已拼好的木棍长度加上当前长度不大于要验证的长度,且还有该长度的木棍
{
--a[i],dfs(x,i,v+i,ans),++a[i];//将该长度的木棍的根数减1,dfs,然后回溯
if(v+i==ans||!v) break;//如果已拼好的木棍长度加上当前长度刚好等于要验证的长度,或者没有已拼好的木棍,则无论如何都不会比选这根木棍要优,因此退出循环,结束枚举
}
}
}
int main()
{
register int i;int x,sum=0;
read(n);
for(i=1;i<=n;++i)
{
read(x);
if(x>50) continue;//按照题目要求,自动过滤超过50的长度
++a[x],maxx=max(maxx,x),minn=min(minn,x),sum+=x;//更新每种长度的木棍根数、最长的木棍的长度、最短的木棍的长度、木棍长度和
}
for(i=maxx;;++i)//从最长的木棍的长度开始枚举
if(!(sum%i)) dfs(sum/i,maxx,0,i);//最终答案肯定是sum的因数,用dfs来验证
}

最新文章

  1. AspNetPager分页控件样式的使用
  2. 关于XML中:XmlNode和XmlElement的涵义及不同之处
  3. shell中$0,$?,$!等的特殊用法
  4. Atitit java 二维码识别 图片识别
  5. CString 操作
  6. hrbustoj 1545:基础数据结构——顺序表(2)(数据结构,顺序表的实现及基本操作,入门题)
  7. 服务器安装MongoDB
  8. js webstorm用法
  9. Wonderful Sentense
  10. Designing Evolvable Web API with ASP.NET 随便读,随便记 “The Internet,the World Wide Web,and HTTP”——HTTP
  11. 在Code first中使用数据库里的视图
  12. 标准I/O库之流和FILE对象
  13. JAVA面试题相关基础知识
  14. Sticks(Central Europe 1995) (DFS)
  15. 手机触摸屏的JS事件
  16. Swift - 获取字符串的MD5值
  17. 安全扫描工具-AppScan
  18. POJ置换群入门[3/3]
  19. 微软Surface Book推送Windows 10新固件更新:增强系统和电池
  20. Python内置函数(61)——eval

热门文章

  1. 2018CCPC网络赛A(优先队列,思维)
  2. php 获取当前的访问的ip
  3. java实例练习——基于TCP/IP协议的多客户端通信
  4. InfoQ —— 腾讯游戏大数据服务场景与应用
  5. PJzhang:英国通信总部GCHQ开源产品-网络瑞士军刀CyberChef
  6. shiro 重定向 后 带有 sessionId 的 解决 办法
  7. Jmeter4.0----正则表达式提取器(12)
  8. C# Task任务详解及其使用方式
  9. 在SpringBoot中使用Docker(利用dockerfile-maven-plugin插件)
  10. CSU 1453: 平衡序列 学会线段树后必做