Luogu P1120 Small Stick [Data Enhanced Edition]

topic

Title:

There are some small sticks of the same length, and these sticks are randomly chopped into several pieces, until each piece is no more than 50 inches long. Enter the length of each cut stick to find the minimum possible length of the original stick.

answer:

Search, add some pruning, see the standard program for details

Standard range:

#include<bits/stdc++.h>
using namespace std;
int n,i,sum,mx,x,a[65],use[65],cnt;
int cmp(int x,int y){
    return x>y;
}
void dfs(int ans,int s,int g,int now){//ans为当前还原的木棍长度
//s为已还原的木棍个数,g为每根木棍目标长度,now为匹配到第几根木棍
    if (s*g==sum){
        printf("%d",g);
        exit(0);
    }
    if (a[cnt-1]+ans>sum) return;//加上最短的一根都大,那肯定不行
    if (ans==g){//达到每根木棍的目标长度
        dfs(0,s+1,g,0);
        return;
    }
    for (int i=now;i<cnt;i++)
        if (!use[i] && ans+a[i]<=g){
            use[i]=1;
            dfs(ans+a[i],s,g,i+1);
            use[i]=0;
            if (ans+a[i]==g || !ans) break;
//若某组拼接不成立,且此时已拼接的长度为0
//或当前已拼接的长度与刚才枚举的长度之和为最终枚举的答案时,则可直接跳出循环
//因为此时继续枚举其它更小的值时,显然可能情况更少,且同样凑不完。
            while (a[i]==a[i+1]) i++;
        }
}
int main(){
    cin>>n;
    for (i=0;i<n;i++){
        scanf("%d",&x);
        if (x<=50) a[cnt++]=x,sum+=x,mx=max(mx,x);//要把超过50的长度过滤掉
    }
    sort(a,a+cnt,cmp);
    for (i=mx;i<=sum/2;i++)//枚举最小可能长度
        if (sum%i==0) dfs(0,0,i,0);//每根木棍还原后长度相等,所以i一定整除sum
    cout<<sum;
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326803263&siteId=291194637