acwing 167 木棒代码解释

复制代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n;
int sum;
int length;
int a[100];
bool st[100];
bool dfs(int u,int part,int start)
{
    if(u*length==sum)
    {
        return true;
    }//dfs一般最前面是一个底层终结选项
    if(part==length)//dfs一般次前面有一个迭代选项
    {
        if(dfs(u+1,0,0))
        return true;
        else
        return false;
    }
    for(int i=start;i<n;i++)
    {
        if(st[i])
        continue;
        if(part+a[i]>length)
        continue;
        st[i]=1;
        if(dfs(u,part+a[i],i+1))
        return true;
        st[i]=0;//恢复
        if(part==0||part+a[i]==length)
        {
            return false;
        }
//剪枝3和剪枝4:剪枝3的意思是当前木棍开始拼接,如果对于当前的木棒来说,接下来的方案是失败的,则需要回到之前的操作,不用继续枚举后面的木棒了,反证法证明:第一种当前木棒刚刚好放下去当前木棍,但是
//后面无法拼接,方案失败,假设方案仍能成功的,那么我们对于当前的木棍采取其他的木棒进行拼接,接下来由于刚刚讨论的木棒是最大的,所以对于下一个木棍它也是第一个拼接,但是我们的假设是方案是成功的,所
//前后矛盾,所以鲲鲲了。第二种是当前的木棒与其他的木棒结合也无法拼接成当前的木棍,假设方案成功,第一个木棍由其他的木棒拼接成功,但是第二个木棍也还要由这个木棒进行拼接,所以一鲲鲲再鲲鲲。当前的木
//棒与其他的木棒恰好拼接成当前的木棍,后面无法拼接,方案失败,假设方案仍能成功,那么我们可以用除了上述的木棒之外的木棒进行拼接,我们将上述的木棒来拼接下一根木棍,是无法拼接成功的,所以反证成功。
//剪枝4:当前木棍的长度加上当前的木棒的长度恰好等于length,但是后面的方案是失败的,假设方案是成功的,那么当前的木棒的长度就由其他的木棒或者木棒们进行填充,长度是相等的,可以互换,但是这里方案是
//成功的,与现实失败是矛盾的,所以寄
int j=i; while(j<n&&a[j]==a[i]) { j++; } i=j-1; }//剪枝5:对于接下来的木棒,如果与当前gg的木棒长度是相等的,直接跳过 return false; } int main() { while(cin>>n,n) { sum=0; length=1; memset(st,0,sizeof st);//判断当前木棒是否已经被之前的操作选走了 for(int i=0;i<n;i++) { cin>>a[i]; sum+=a[i]; } sort(a,a+n); reverse(a,a+n);//剪枝1:将木棒从大到小排列,导致每一根木棍的拼接选择更少,减少分支 while(1) { if(sum%length==0&&dfs(0,0,0))//剪枝2:条件1放在前面可以减少进行dfs判定的次数 { cout<<length<<endl; break; } length++; } } return 0; }
复制代码

 

posted @   ggoodstudyddayup  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示