Sticks_cdoj_有注释的

 http://acm.ccucomp.cn/acmhome/problemdetail.do?&method=showdetail&id=1113

  1 #include<iostream>
  2 #include<algorithm>
  3 
  4 using namespace std;
  5 
  6 int n,sum,len;
  7 int count;
  8 int sticks[65];
  9 int cmp(const void *a, const void *b)  //  比较函数
 10 {
 11     return *(int *)b - *(int *)a; 
 12 }
 13 
 14 bool used[65];
 15 
 16 bool dfs(int pos,int cur, int count)           //pos = postion 当前搜到的位置,cur=current 当前搜到的位置的棍子的长度
 17 {
 18     int flag;                                 // 不能使全局变量,标记 cur是不是为零,以方便下面的剪枝操作
 19     if(cur == 0)
 20         flag = true;
 21     else flag=false;
 22     if(count == sum/len)                     // 如果搜到了len即返回 得到所要结果
 23         return true;
 24     for(int i = pos; i < n; i++)              // 从当前位置遍历
 25     {
 26         if(used[i]==false)continue;           //判断是否被遍历过
 27          if(cur + sticks[i] == len)           // 如果 相等 则找到一根棍子 
 28         {
 29              used[i] = false;                   //  标记该段 被用过
 30             if(dfs(0,0,count+1))return true;    //继续判断其他段是否也能满足 该len
 31             used[i] = true;                      // && 深搜的特征  上一步运行结束,程序得从i 继续重新开始
 32             return false;                        // 该 cur + sticks[i] 不满足此时情况,需要判断cur和其他的sticks的组合
 33          }    
 34          
 35          else if(cur + sticks[i] < len)           //
 36          {
 37              used[i] = false;                    //
 38             if(dfs(i+1,cur+sticks[i],count))       // 因为当前 cur+sticks[i]< len所以还需要再跟其他的sticks【】组合
 39                 return true;                       //判断是否满足情况
 40             used[i] = true;                         // 同上 &&
 41             if(flag)return false;                    // 是一剪枝 操作(即当前没有满足情况,就不用再继续循环了)
 42             while(sticks[i] == sticks[i+1])          // 亦是剪枝,如果cur+sticks[i] == cur+sticks[i+1],即不用再经过以上的深搜了。
 43                  i++;
 44              }
 45          }    
 46     return false;                        //遍历的结果没有 就返回false,继续 主函数的循环,len增加1
 47 }
 48 
 49 int main()
 50 {
 51     int i;
 52     while(scanf("%d",&n)!=EOF)
 53     {
 54         if(n == 0)
 55             break;
 56         sum = 0;
 57         int cou = 0;
 58         for(i = 0; i < n; i++)
 59         {
 60             cin>>sticks[i];   //输入每段棍子长度
 61             sum += sticks[i];  // 计算总共长度
 62             used[i] = true;    //初始化 used  深搜dfs时候以此来标记每段棍子 是否合并过 
 63         }
 64         
 65         qsort(sticks,n,sizeof(sticks[0]),cmp);//是快速排序,如果用sort(sticks,sticks+n,cmp)的话 cmp 为bool型的
 66 
 67         for(len = sticks[0]; len <= sum; len++)  // 最长就是sum,即一根棍子  被切了这n段
 68         {
 69             if(sum%len == 0)                   //如果有 长度是len,必然能被sum整除,因为是整数条棍子
 70             {
 71                 if(dfs(0,0,0))                 // 从零开始深搜 如果搜到 即停止, 得到最小len。
 72                     break;
 73             }
 74         }
 75         cout<<len<<endl;                      //输出结果
 76 
 77 
 78     }
 79     return 0;
 80 }
 81 
 82 /*
 83 测试数据:
 84 9
 85 5 2 1 5 2 1 5 2 1
 86 4
 87 1 2 3 4
 88 4
 89 1 2 5 9
 90 9
 91 15 3 2 11 4 1 8 8 8
 92 64
 93 40 40 30 35 35 26 15 40 40 40 40 40 40 40 40 40 40 40 40 40 40 
 94 40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40 
 95 40 25 39 46 40 10 4 40 40 37 18 17 16 15 40 40 40 40 40 40 40 
 96 40
 97 64 
 98 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
 99 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
100 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 
101 1
102 0
103 
104 
105 
106 
107 */

 

posted @ 2012-04-12 20:31  南柯南  阅读(175)  评论(0编辑  收藏  举报