UVA 307Sticks(dfs搜索)

本文探讨了一道经典的分配问题——如何将多个不同长度的木棍分配到若干组中,使得每组木棍的总长度相等,并给出了通过搜索算法解决此问题的方法及实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大体题意:

给你n个木棍,要求分配这个n 个木棍到x组,使得x组的木棍长度和都相同,问最小的长度和是多少?

思路:

直接搜索:

需要加很多剪枝才能过:

1.首先你枚举时,应该枚举组数,而不是长度和,否则循环会很长。

2.如果第一个木棍选完了,没找到合适的使它权值和为枚举的答案,就不可能有答案了。

3.如果第i个木棍能组成ans,但其余的不能了,也不能有答案了。

4.当长度小于ans时,前面的不用在循环了,直接从当前位置继续往后找就好了。

5.if else if 写成if else 的话,容易漏掉长度和 > ans的情况。。。。坑死了这里。。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 500 + 7;
int a[maxn], n, f, g, df;
bool vis[maxn];
bool cmp(int& a,int& b){
    return a > b;
}

bool dfs(int cur,int c,int pos,int len){
    if (cur == f) {
        if (len == n)return true;
        return false;
    }

    for (int i = pos; i < n; ++i){
        if (!vis[i]){
            if (c+a[i] == g){
                vis[i] = 1;
                if (dfs(cur+1,0,0,len+1)) return true;
                vis[i] = 0;
                return false;
                while(i+1 < n && a[i+1] == a[i])++i;
            }
            else if (c+a[i] < g){
                vis[i] = 1;
                if ( dfs(cur,c+a[i],i+1,len+1) ) return true;
                vis[i] = 0;
                while(i+1 < n && a[i+1] == a[i])++i;
            }
            if (!pos)return false;
        }
    }

    return false;
}

int main(){
    while (~scanf("%d",&n) && n){

        int sum = 0;
        bool ok = 1;
        for (int i = 0; i < n; ++i) {
            scanf("%d",a+i);
            sum += a[i];
            if (i){
                if (a[i] != a[i-1])ok = 0;

            }
        }

        if (ok) {
            printf("%d\n",a[0]);
            continue;
        }

        sort(a,a+n,cmp);

        int ans = sum;

        for (int i = n - 1; i > 1; --i){
            if (sum % i == 0 && sum / i >= a[0]){
                f = i;
                g = sum/i;
                memset(vis,0,sizeof vis);
                if (dfs(0,0,0,0)){
                    ans = g;
                    break;
                }
            }
        }
        printf("%d\n",ans);
    }



    return 0;
}
/**
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0

**/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值