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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】