UVA10364 题解
题意简述
给定
题目分析
这道题和 P1120 很像,都考察了对于 DFS 的剪枝优化。
具体地,我们有以下几个剪枝策略
-
计算出每根木棍的长度之和,记为
,若 ,则直接输出no
。 -
将每一根木棍按长度从大到小排序,优先尝试将长度更长的木棍拼入正方形中。
-
若下一层搜索返回失败,则不再尝试将长度和上一次拼入正方形的木棍的长度一样的木棍拼入正方形。
-
若下一层搜索返回失败,且当前拼出的边的长度为
则直接返回失败。原因是其他没有拼过的边和当前在考虑的空的边是等效的,将某跟木棍拼入当前的边若失败,则将该木棍拼入其他空的边同样会失败。 -
若将当前考虑的某根木棍拼入当前考虑的边后,边长达到了要求,但后续的搜索返回失败,则直接返回失败。原因是较短的木棍比较长的木棍更优,当为后续的搜索留下更多更短的木棍都无法拼成时,若在当前使用更短的木棍,则后续的搜索一定无法成功。
讲得可能不太好,所以具体实现看代码。
Code
#include<bits/stdc++.h> using namespace std; int T,n,a[25],sum; bool vis[25]; bool cmp(int x,int y){ return x>y; } bool dfs(int finish,int now_len,int last){ if(finish>=4) return 1; if(now_len==sum) return dfs(finish+1,0,1); int never=0; for(int i=last;i<=n;i++){ if(!vis[i] && now_len+a[i]<=sum && never!=a[i]){ vis[i]=1; if(dfs(finish,now_len+a[i],i+1)) return 1; never=a[i]; vis[i]=0; if(!now_len || now_len+a[i]==sum) return 0; } } return 0; } int main(){ cin>>T; while(T--){ cin>>n; sum=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){ cin>>a[i]; sum+=a[i]; } if(sum%4!=0){ puts("no"); continue; } sort(a+1,a+1+n,cmp); sum/=4; if(dfs(0,0,1)==1) puts("yes"); else puts("no"); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】