标签:解释 就是 cst oid sizeof 重要 不用 turn 思路
//原址有中文翻译
求出总长度sum和小棒最长的长度max,则原棒可能的长度必在max~sum之间,然后从小到大枚举max~sum之间能被sum整除的长度len,用dfs求出所有的小棒能否拼凑成这个长度,如果可以,第一个len就是答案。
下面就是关键的了,就是这道题dfs的实现和剪枝的设计:
1.以一个小棒为开头,用dfs看看能否把这个小棒拼凑成len长,如果可以,用vis[i]记录下用过的小棒,然后继续以另外一个小棒为开头,以此类推。
2.小棒的长度从大到小排序,这个就不解释了。
3.如果当前最长的小棒不能拼成len长,那么就返回前一步,更改前一步的最长小棒的组合情况(这里不能是全部退出),不用再继续搜索下去了。
4.最重要的,就是比如说17,9,9,9,9,8,8,5,2……如果当前最长小棒为17,它与第一个9组合之后dfs发现不能拼成len,那么17就不用和后面所有的9组合了,而直接和8开始组合。这个剪枝直接从TLE到16MS,很强大。
//转自http://blog.sina.com.cn/s/blog_6635898a0100lgq0.html
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 int n,a[70],ans; 9 bool flag,vis[70]; 10 11 bool cmp(int k,int b) { 12 return k > b; 13 } 14 15 inline void dfs(int deep,int now,int i) { 16 if(flag) return ; 17 if(now == 0) { 18 int k = 0; 19 while(vis[k]) k++; 20 vis[k] = true; 21 dfs(deep + 1,a[k],k + 1); 22 vis[k] = false; 23 return ; 24 } 25 if(now == ans) { 26 if(deep == n + 1) flag = true; 27 else dfs(deep,0,1); 28 return ; 29 } 30 for(int j = i;j <= n; j++) { 31 if(!vis[j] && now + a[j] <= ans) { 32 if(!vis[j-1] && a[j] == a[j-1]) continue; 33 vis[j] = true; 34 dfs(deep + 1,now + a[j],j + 1); 35 vis[j] = false; 36 } 37 } 38 } 39 40 int main() 41 { 42 while(true) { 43 scanf("%d",&n); 44 if(n == 0) return 0; 45 flag = false; 46 int sum = 0; 47 for(int i = 1;i <= n; i++) { 48 scanf("%d",&a[i]); 49 sum += a[i]; 50 } 51 sort(a + 1,a + n + 1,cmp); 52 for(ans = a[1];ans < sum; ans++) 53 if(sum % ans == 0) { 54 memset(vis,0,sizeof(vis)); 55 dfs(0,0,1); 56 if(flag) break; 57 } 58 printf("%d\n",ans); 59 } 60 return 0; 61 }
标签:解释 就是 cst oid sizeof 重要 不用 turn 思路
原文地址:https://www.cnblogs.com/lipeiyi520/p/11487527.html