307 - Sticks (深搜 + 剪枝)

来源:互联网 发布:pdg mac 编辑:程序博客网 时间:2024/06/06 09:18

由于要求最小长度,所以可以从小到大枚举木棍的长度 ,显然,木棍最小值为所给木棍的最大值 。 所以从该值开始枚举木棍长度,则木棍如果大于所有木棍之和,那么答案肯定就是所有之和了 。

该题时间卡的比较紧,需要努力剪枝 ,总的来说就是找到几种肯定不会得到最优解的情况,然后直接回溯 。

细节见代码:

#include<bits/stdc++.h>using namespace std;const int maxn = 10000;int n,a[maxn],vis[maxn],maxd,sum;bool cmp(int a,int b) {    return a > b ;}bool dfs(int cur,int d, int len) {    if(len == maxd) {        d++;        if(d == sum/maxd) return true;        for(cur = 0 ; vis[cur] ;cur++) ;            vis[cur] = 1;            if(dfs(cur+1,d,a[cur])) return true;            vis[cur] = 0;    }    else {        for(int i=cur;i<n;i++) {            if(!vis[i] && a[i]+len <= maxd) {                if(i != 0 && a[i] == a[i-1] && !vis[i-1]) continue;//剪枝                vis[i] = 1;                if(dfs(i+1,d,a[i]+len)) return true;                vis[i] = 0;                if(a[i] == maxd - len) return false;//剪枝            }        }    }    return false;}int main() {    while(~scanf("%d",&n)&&n) {        sum = 0;        for(int i=0;i<n;i++) scanf("%d",&a[i]) , sum += a[i];        sort(a,a+n,cmp);        memset(vis,0,sizeof(vis));        for(maxd = a[0]; maxd <= sum/2 ; ++maxd) {            if(sum%maxd!=0) continue;            if(dfs(0,0,0)) break;        }        if(maxd > sum/2) printf("%d\n",sum);        else printf("%d\n",maxd);    }    return 0;}


1 0
原创粉丝点击