P1120小木棍

Posted vimin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1120小木棍相关的知识,希望对你有一定的参考价值。

题目传送P1120

有许多剪枝的搜索

  • 先考虑答案的范围,先把小木棍排个序,原木棍的长一定大于等于最长的一根
  • 然后,就枚举一下原木棍的长度,搜是否能按这个长度拼成所有的木棍,如果能拼成直接就是答案了
  • 确定了原始长度,然后用总长度就能算出原始木棍的条数。如果不能整除的话,肯定不是答案
  • 然后确定搜索的状态,当前拼到第几跟,这一根还剩多长,拼这一根用的上一根小木棍的编号
  • 我们肯定要先拼大的,再用小的去补大的
  • 如果我们用小的凑的话,那些大的很难凑齐
  • 还有一个优化就是,有很多长度相同的小木棍,对于一种长度不能拼的话我们要直接略过剩下和它长度相同的。就预处理出$net$数组
  • 还有剪枝,如果这根小木棍正好等于剩下的长度,却没有成功。这是最优的情况都没有成功,说明这种情况不会合法了
  • 还有剪枝,如果这根小木棍等于原长却没被用上,说明这也是不合法的(这两个剪枝会剪掉4个点

    代码

#include<iostream>
#include<algorithm>
using namespace std;
inline int read()
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9')if(ch=='-') w=-1;ch=getchar();
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;

int n,x,num,tag,s,len;
int a[100],book[100],net[100];
bool cmp(int a,int b)
    return a>b;

void dfs(int now,int last,int res)
    if(!res)// now 当前是第几个,last拼的上一段的编号,res剩下的长度 
        if(now==num) 
            tag=1;
            return ;
        
        
        for(int i=1;i<=n;i++)
          if(!book[i])
            book[i]=1;
            dfs(now+1,i,len-a[i]);
            book[i]=0;
            if(tag) return ;
            break;
          
    
    int l=last+1,r=n,mid;
    while(l<=r)
        mid=(l+r)>>1;
        if(a[mid]>res) l=mid+1;
        else r=mid-1;
    
    for(int i=l;i<=n;i++)
      if(!book[i])
        book[i]=1;
        dfs(now,i,res-a[i]);
        book[i]=0;
        if(tag) return ;
        if(a[i]==res||res==len) return ;
        i=net[i];
        if(i==n) return ;
      

int main()

    x=read();
    for(int i=1;i<=x;i++)
        int xx;
        xx=read();
        if(xx<=50) 
            a[++n]=xx;
            s+=xx;
        
    
    sort(a+1,a+n+1,cmp);
    for(int i=n;i>=1;i--)
      if(a[i]==a[i+1]) net[i]=net[i+1];
      else net[i]=i;
    for(len=a[1];len<=s/2;len++)
        if(s%len) continue;
        num=s/len;
        book[1]=1;
        tag=0;
        dfs(1,1,len-a[1]);
        book[1]=0;
        if(tag)printf("%d",len);return 0;
    
    printf("%d",s);
    return 0;
  

以上是关于P1120小木棍的主要内容,如果未能解决你的问题,请参考以下文章

洛谷 P1120 小木棍

洛谷P1120 小木棍

P1120 小木棍 [数据加强版] 题解

P1120 小木棍 [数据加强版]

题解 P1120 小木棍 [数据加强版]

luogu P1120 小木棍 [数据加强版]