poj 1011 解题报告

来源:互联网 发布:软件方面的证书 编辑:程序博客网 时间:2024/06/10 17:22
题目http://acm.pku.edu.cn/JudgeOnline/problem?id=1011
被这个题困扰了几天,开始的时候用贪心,速度很快但是结果WA,贪心不可以的原因是没有搜索到所有可能的结果集,长优先并不一定是最好的结果。
后来用深度优先搜索+剪枝 结果TLE,郁闷了半天开始优化剪枝,直到AC, 结果还是花了32MS,不知道那些0MS的大牛们怎么优化出来的,反正我是快崩溃了,不想再整这个题了。

首先说一下这个题的解题思想。

1.选取某一个开始长度,开始组合小木棒,这个开始长度的限制条件为 不小于木棒最大长度,不大于所有木棒长度和,能被长度和整除
2.从可用的最长的那根小木棒开始组合木棒,找出所有的结果集,找到结果集后开始组合下一根木棒。
3.直到所有的小木棒都被组合完成,搜索结束。

  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <vector>
  4. #include <algorithm>
  5. using namespace std;
  6. int sticksNum; //木棒个数 
  7. int totalLen; //总长度 
  8. int caseNum; //应该组合得到的木棒数
  9. vector<int> sticks;//存放小木棒长度
  10. vector<int> used;//记录木棒使用状态 
  11. bool searchSticks(int index,int len,int complete); 
  12. bool searchResult(int index,int nowLen,int len,int start,int complete) //从index开始 搜索长度为len 完成长度为 nowLen 木棒 complete 已完成数
  13. {
  14.      if(nowLen==len)
  15.      {
  16.         return (searchSticks(start-1,len,complete+1));        
  17.      }
  18.      else if(nowLen>len)   //优化 若当前长度大于总长度 不符合条件
  19.      {
  20.         return false;
  21.      }
  22.      if(index==-1)   
  23.          if(nowLen==len)
  24.             return (searchSticks(start-1,len,complete+1));  
  25.          else
  26.             return false;
  27.      if(index==0)
  28.      {
  29.         if(used[index]==0)
  30.         {
  31.               if(nowLen==0)
  32.               {
  33.                   return (searchSticks(start-1,len,complete+1));
  34.               }
  35.               else
  36.               {
  37.                   return false;
  38.               }
  39.         }
  40.         else
  41.         {
  42.             if(nowLen+sticks[0]!=len)
  43.               return false;
  44.             else
  45.             {
  46.                 used[index]=0;
  47.                 if(searchSticks(start-1,len,complete+1))
  48.                 {
  49.                   return true;
  50.                 }
  51.                 else
  52.                 { 
  53.                   used[index]=1; 
  54.                   return false;
  55.                 }
  56.             }
  57.         }
  58.      }
  59.          
  60.      if(used[index]==0)
  61.      {
  62.            return searchResult(index-1,nowLen,len,start,complete);
  63.      }
  64.      else
  65.      {
  66.           if(nowLen+sticks[index]>len)
  67.             return searchResult(index-1,nowLen,len,start,complete);
  68.           else if(nowLen+sticks[index]==len)
  69.           {
  70.                used[index]=0;
  71.                if(searchSticks(start-1,len,complete+1))
  72.                {
  73.                   return true;
  74.                }
  75.                else
  76.                {
  77.                  used[index]=1; 
  78.                  return false;
  79.                }
  80.           }
  81.           else
  82.           {
  83.               int tempLen=0;              
  84.               for(int i=index;i>=0;--i)
  85.               {              
  86.                  if(tempLen==sticks[i]||used[i]==0)  //优化 若该小木棒已被用过 或前面小木棒长度和它相同 则没必要再搜索下去
  87.                    continue;
  88.                  tempLen=sticks[i]; 
  89.                  used[i]=0;                                                     
  90.                  if(searchResult(i-1,nowLen+tempLen,len,start,complete))
  91.                  {
  92.                    return true;
  93.                  }
  94.                  else
  95.                  {
  96.                    used[i]=1;
  97.                  }
  98.               }
  99.               return false;
  100.           }           
  101.      }
  102. }
  103. bool searchSticks(int index,int len,int complete)//组合以index开始的木棒 
  104. {
  105.      if(index==-1)
  106.        return true
  107.      if(used[index]==0)
  108.        return searchSticks(index-1,len,complete);
  109.      if((caseNum-complete)>(index+1))   //优化:若还应该组合得到的木棒数大于当前剩余的小木棒数 则不符合条件
  110.          return false;
  111.        
  112.      int nowLen=sticks[index];
  113.      if(nowLen==len)
  114.      {
  115.         used[index]=0; 
  116.         if(searchSticks(index-1,len,complete+1))
  117.         {
  118.           return true;
  119.         }
  120.         else
  121.         {
  122.             used[index]=1;
  123.             return false;
  124.         }
  125.      }
  126.       used[index]=0;     
  127.       if(searchResult(index-1,nowLen,len,index,complete))
  128.       {
  129.          return true;                                      
  130.       }
  131.       else
  132.       {
  133.          used[index]=1;
  134.          return false;   
  135.       } 
  136. }
  137. int main(int argc, char *argv[])
  138. {
  139.     while(cin>>sticksNum&&sticksNum!=0)
  140.     {
  141.         totalLen=0;
  142.         int tempLen; 
  143.         used.clear();
  144.         sticks.clear();
  145.         
  146.         for(size_t index=0;index<sticksNum;++index)
  147.         {
  148.             cin>>tempLen;
  149.             totalLen+=tempLen;
  150.             sticks.push_back(tempLen);
  151.                                
  152.         }
  153.         sort(sticks.begin(),sticks.end());  //优化:从小到大排列木棒 大木棒在搜索过程中享有优先权        
  154.         int startLen=sticks[sticksNum-1];       
  155.         for(int len=startLen;len<=totalLen;++len) //优化 搜索从小木棒最大长度开始
  156.         {
  157.                 if(totalLen%len==0)//优化 只有能被总长度整除的长度 才合法
  158.                 {
  159.                      caseNum=totalLen/len;
  160.                      used=vector<int>(sticksNum,1);
  161.                      if(searchSticks(sticksNum-1,len,0))
  162.                      {
  163.                        cout<<len<<endl;
  164.                        break;
  165.                      }
  166.                 } 
  167.         }                          
  168.     } 
  169. //    system("PAUSE");
  170.     return EXIT_SUCCESS;
  171. }
终于AC了.......

附一组测试数据

915 3 2 11 4 1 8 8 866 2 2 4 8 851 1 1 1 1 21 142 2 9 931 2 36440 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 43 42 42 41 10 4 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 749 48 47 46 45 44 4373 4 5 5 5 5 1372 7 7 7 7 10 2061 2 3 11 11 20763 2 44 12 60 35 60 95 2 1 5 2 1 5 2 141 2 3 40//答案:15 11 8 8 8 4 3 2 1第1 of 3根木棍:15+3+2=20第2 of 3根木棍:11+8+1=20第3 of 3根木棍:8+8+4=20第1组测试数据结果:208 8 6 4 2 2第1 of 3根木棍:8+2=10第2 of 3根木棍:8+2=10第3 of 3根木棍:6+4=10第2组测试数据结果:101 1 1 1 1第3组测试数据结果:11 1第4组测试数据结果:19 9 2 2第1 of 2根木棍:9+2=11第2 of 2根木棍:9+2=11第5组测试数据结果:113 2 1第2 of 2根木棍:2+1=3第6组测试数据结果:364个BT数字:第1 of 2根木棍:43+42+42+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+4=1251第2 of 2根木棍:41+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+40+10=1251第7组测试数据结果:125149 48 47 46 45 44 43第1 of 1根木棍:49+48+47+46+45+44+43=322第8组测试数据结果:32213 5 5 5 5 4 3第1 of 2根木棍:13+4+3=20第2 of 2根木棍:5+5+5+5=20第9组测试数据结果:2020 10 7 7 7 7 2第1 of 2根木棍:20+10=30第2 of 2根木棍:7+7+7+7+2=30第10组测试数据结果:3020 11 11 3 2 1第1 of 2根木棍:20+3+1=24第2 of 2根木棍:11+11+2=24第11组测试数据结果:2463 60 60 44 35 12 2第1 of 1根木棍:63+60+60+44+35+12+2=276第12组测试数据结果:2765 5 5 2 2 2 1 1 1第1 of 4根木棍:5+1=6第2 of 4根木棍:5+1=6第3 of 4根木棍:5+1=6第4 of 4根木棍:2+2+2=6第13组测试数据结果:64 3 2 1第1 of 2根木棍:4+1=5第2 of 2根木棍:3+2=5第14组测试数据结果:5
原创粉丝点击