洛谷 P1120 小木棍[数据加强版]

这道题可能是我做过的数据最不水的一道题……


题目传送门

这题可以说是神剪枝,本身搜索并不算难,但剪枝是真不好想(好吧,我承认我看了题解)……

剪枝:

  • 用桶来存储木棍
  • 在输入的时候记录下最长的木棍和最短的木棍和木棍的总长
  • 搜索时保证目前答案能整除木棍
  • 搜索时记录下上一层的木棍长度,然后从该木棍的长度到小进行枚举
  • 如果搜回来发现当前木棍长度等于答案,那么直接return

大的剪枝就这些了,还有一些小剪枝,具体还是看代码吧:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int read(){
    int k=0; char c=getchar();
    for(;c<'0'||c>'9';) c=getchar();
    for(;c>='0'&&c<='9';c=getchar())
      k=(k<<3)+(k<<1)+c-48;
    return k;
}
int n,tot,a[101];
int maxn,minn=100000;
void dfs(int sum,int ans,int hhh,int maxx){
    if(!hhh){
        printf("%d",ans);
        exit(0);
    }
    if(sum==ans){
        dfs(0,ans,hhh-1,maxn);
        return ;
    }
    for(register int i=maxx;i>=minn;i--){
        if(sum+i<=ans&&a[i]){
            a[i]--;
            //cout<<a[i]<<endl;
            dfs(sum+i,ans,hhh,i);
            a[i]++;
            if(sum==0||sum+i==ans)
              break;
        }
    }
    return ;
}
int main(){
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    n=read();
    for(register int i=1;i<=n;i++){
        int x=read();
        if(x>50) continue;
        a[x]++; tot+=x;
        maxn=max(maxn,x);
        minn=min(minn,x);
    }
    int zz=tot>>1;
    for(register int i=maxn;i<=zz;i++){
        if(tot%i==0){
            dfs(0,i,tot/i,maxn);
        }
    }
    printf("%d",tot);
    return 0;
}
/* 赠送一组数据 QWQ
64
1 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 2 2 1 1 2 2 1 2 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 2 1 1

13
*/
上一篇:AC日记——妖梦拼木棒 洛谷 P3799


下一篇:Linux环境搭建Hadoop伪分布模式