确实是一道经典的深搜好题,(不过POJ不都是这样吗……)。
首先这道题爆搜就死定了,所以咱们考虑一些剪枝。
1.对所有的木棍按长度降序排序,先尝试较长的木棍,这样可以减少搜索树的分支。
2.定义一个变量,记录最近一次搜索失败的木棍的长度,若即将搜索的长度与之相等,则直接跳过。
3.如果在原始木棒“加入第一根”就搜索错误,那么直接返回错误,因为剩下的原始木棒都是一样的。
4.如果加入一根木棒,当前的原始木棒恰好拼接完成,而之后的拼接返回错误,则直接返回错误。因为用一根长木棍拼接完成一定比用若干根短木棍拼接完成更好。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 typedef long long ll; 6 using namespace std; 7 int n,a[70],maxx,minn,tot,len; 8 bool vis[70]; 9 bool dfs(int done,int now,int last) { 10 if(done>tot) return 1; 11 if(now==len) return dfs(done+1,0,1); 12 int x=0; 13 for(int i=last;i<=n;i++) 14 if(!vis[i]&&x!=a[i]&&a[i]+now<=len) { 15 vis[i]=1; 16 if(dfs(done,now+a[i],i+1)) return 1; 17 x=a[i]; 18 vis[i]=0; 19 if(now==0||now+a[i]==len) return 0; 20 } 21 return 0; 22 } 23 int main() { 24 memset(a,0,sizeof(a)); 25 maxx=minn=0; 26 for(int i=1;i<=n;i++) { 27 cin>>a[i]; 28 maxx+=a[i]; 29 minn=max(a[i],minn); 30 } 31 sort(a+1,a+n+1); 32 reverse(a+1,a+n+1); 33 for(len=minn;len<=maxx;len++) 34 if(maxx%len==0) { 35 tot=maxx/len; 36 memset(vis,0,sizeof(vis)); 37 if(dfs(1,0,1)) break ; 38 } 39 cout<<len<<endl; 40 return 0; 41 }