标签:
题目大意:给出一些长度不大于 50 的木棍, 要求你把这些小木棍拼成
长度相同木棍,当然长度越小越好。
剪枝:
1.最长的木棍的长度一定不会超过以前的木棍长度,所以从最长的长度开始枚举
2.如果总长度不能被选中的长度整除剪掉
3.如果所求木棍数等于总长度除以所枚举的木棍长度返回,不要再向下搜索
4.每加入一个木棍做一下标记,以免被再次搜索
5.从大到小排序,这样如果当前的不能被加入,太大了,只要往后搜小的就行
6.如果向下搜索失败回退回来,下一根木块与当前这根碎木块长度相同,则不需要对他进行搜索了,直接跳过
自己写的超时代码,水平不够,继续努力
1 import java.util.Arrays; 2 import java.io.BufferedReader; 3 import java.io.InputStreamReader; 4 import java.util.StringTokenizer; 5 6 public class Main{ 7 static int lens[]; 8 static boolean visit[]; 9 10 public static boolean dfs(int len,int cur,int index,int cnt,int j,int n){ // len目标长度,cur当前木棍的长度,index木棍的下标, 11 if(cnt == j){ //cnt已经拼成的目标木棍数量,j总共需拼成的目标木棍的数量 12 return true; 13 } 14 else if(len == cur){ 15 return dfs(len,0,0,cnt+1,j,n); 16 } 17 18 else{ 19 int i; 20 int sample = -1; 21 for(i=index;i<n;i++){ 22 if(visit[i]==false && lens[i]!=sample && cur +lens[i]<=len){ 23 visit[i]=true; 24 if(dfs(len,cur+lens[i],i+1,cnt,j,n)){ 25 return true; 26 } 27 sample = lens[i]; 28 visit[i] = false; 29 } 30 if(len==0) 31 break; 32 } 33 return false; 34 } 35 } 36 37 public static void main(String[] args) throws Exception{ 38 int n; 39 BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); 40 while((n = Integer.parseInt(bf.readLine())) != 0){ 41 StringTokenizer take = new StringTokenizer(bf.readLine()); 42 lens = new int[n]; 43 visit = new boolean[n]; 44 45 int index = 0; 46 int result = 0; 47 while (take.hasMoreTokens()) { 48 lens[index] = Integer.parseInt(take.nextToken()); 49 result += lens[index++]; 50 } 51 52 Arrays.sort(lens); 53 for(int len=lens[n-1];len<=result;len++){ 54 if(result%len!=0) //剪枝,原始木棍长度必须能整除所有木棍长度和 55 continue; 56 int j = result/len; 57 if(dfs(len,0,0,0,j,n)){ 58 System.out.println(len); 59 break; 60 } 61 } 62 } 63 } 64 }
标签:
原文地址:http://www.cnblogs.com/yong-hua/p/4482127.html