dfs剪枝(排除等效冗余)

一、剪枝优化

1.优化搜索顺序:有限考虑分支较少的搜索方式,常见的比如从大到小排序
2.排除等效冗余:排除等效的情况,本题就是很好的例子,稍后解释
3.可行性剪枝
4.最优性剪枝

二、本题的排除等效冗余

1.如果是木棒的第一段就搜索失败了,则一定搜不到方案
2.如果是木棒的最后一段搜索失败了,则一定搜索不到方案
3.如果木棒的长度为k的一段搜索失败了,那么后续同样长为k的一段同样也会搜索失败

剪枝3 比较明显,下面证明剪枝1剪枝2

例如:1,1,1,3,.....

对于剪枝1,我们用反证法:假设某个木棒的第一段搜索失败了,存在解决方案
假如开始将 3 作为木棒 a 的第一段搜索失败了,但存在一种合法方案,那么 3 肯定会放在后面的木棒 b 中,但我们交换木棒 a 和木棒 b 的搜索顺序并不会影响答案,因此这与 3 作为木棒 a 的第一段搜索失败矛盾。

对于剪枝2,我们用反证法:假设某个木棒的最后一段搜索失败了,存在解决方案
假如将 3 作为木棒 a 的最后一段搜索失败了,但存在一种合法方案,那么肯定会存在 k(k>1) 根木棒(不妨为 1,1,1 )使得这 k 根木棒作为 a 的最后阶段成功,并且 3 作为木棒 b 的一段成功,同理我们可以将 3 看作木棒 b 的最后一段,而交换木棒 a 和木棒 b 的搜索顺序并不会影响答案,故矛盾。

参考----------->

三、Code

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 70;

int n, w[N];
bool st[N]; // 因为我们需要剪枝实现跳跃,因此需要st标记

// 当前已经恢复了cnt根木棍,每根木棍的长为length
// 当前正在恢复的木棍长为cur
// 下次dfs从start开始遍历w数组
// 所有木棍长度之和为sum
int sum, length;
bool dfs(int cnt, int cur, int start)
{
    if(cnt * length == sum) return true;
    if(cur == length)   return dfs(cnt + 1, 0, 0);
    
    for(int i = start; i < n; i ++ )
    {
        if(!st[i] && cur + w[i] <= length)
        {
            st[i] = true;
            if(dfs(cnt, cur + w[i], i + 1)) return true;
            st[i] = false;
            
            // 走到这里说明第i根木棍放在这没有合法方案
            
        // case1
            if(!cur)    return false;       
        // case2
            if(cur + w[i] == length)    return false; 
        // case3,下一次for从j开始,但下一次dfs仍从start开始
            int j = i;
            while(j < n && w[j] == w[i])    j ++ ;
            i = j - 1;
        }
    }
    return false;
}

int main()
{
    while(cin >> n, n)
    {
        memset(st, false, sizeof st);
        sum = 0;
        for(int i = 0; i < n; i ++ )    cin >> w[i], sum += w[i];
        sort(w, w + n, greater<int>()); // 从大到小排序,优化搜索顺序
        for(length = 1; length <= sum; length ++ )
        {
            if(sum % length == 0 && sum / length <= n && dfs(0, 0, 0))
            {
                cout << length << endl;
                break;
            }
        }
    }
    return 0;
}
posted @   光風霽月  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示