经典剪枝题目,注释的别人代码。还是得自己多敲。反思,反思!
1 #include "iostream" 2 #include "algorithm" 3 #include "memory.h" 4 using namespace std; 5 6 int sticks[64],n,len,num; 7 bool used[64]; 8 9 bool cmp(int a,int b) 10 { 11 return a > b; 12 } 13 14 bool dfs(int cur,int left,int level) 15 { //cur: 当前已经计算的木棒编号,left:该段还剩的长度,level:已经成功的木棒数 16 if (left == 0) {//匹配一根木棒成功 17 if (level == num-2) return true; 18 for (cur = 0; used[cur];cur++);//找到下一个未访问过的长度 19 used[cur] = true; 20 if (dfs(cur+1,len-sticks[cur],level+1)) 21 return true; 22 used[cur] = false; //回溯 23 return false; 24 } else { 25 if (cur >= n-1) return false; 26 for (int i = cur;i < n; ++ i) {//剪枝 27 if (used[i]) continue; //访问过的长度 28 if (sticks[i] == sticks[i-1] && !used[i-1]) continue; //相等的长度已经搜过的不搜 29 if (sticks[i] > left) continue; //大于达到len的生育长度 30 used[i] = true; 31 if (dfs(i,left-sticks[i],level)) return true; 32 used[i] = false; //回溯 33 } 34 return false; 35 } 36 } 37 int main() 38 { 39 while (cin >> n,n) { 40 int sum = 0; 41 for (int i = 0;i < n; ++ i) { 42 cin >> sticks[i]; 43 if(sticks[i]>50) 44 { 45 n--;i--;continue; 46 } 47 sum += sticks[i]; 48 } 49 sort(sticks,sticks + n,cmp);//剪枝 50 bool end = false ; 51 for (len = sticks[0]; len <= sum/2; len++) { 52 if (sum%len == 0) { //剪枝 53 used[0] = true; 54 num = sum/len; 55 if (dfs(0,len-sticks[0],0)) { 56 end = true; 57 cout << len << endl; 58 break; 59 } 60 used[0] = false; //回溯 61 } 62 } 63 if (!end) cout << sum << endl; 64 memset(used,0,sizeof(used)); 65 } 66 return 0; 67 }
时间: 2024-10-15 15:55:34