POJ 1011 Sticks

本文详细解析了POJ1011题目,通过递归算法和状态搜索来解决木棍分组问题,旨在寻找最优解,即如何将输入的木棍长度平均分配成尽可能相等的部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

写这篇文章呢,有个很邪恶的目的,就是提高博客的访问量——据我所知“POJ 1011”这个关键词似乎非常极其的热门——是不是?

当时我做这题的时候的确就写了下面这么长的代码,不过你读一遍就会发现 3/4 的内容都被注释掉了,那些内容多少能说明我的思想,而剩下来的那部分是可以 AC 的。


PS. 我真的不喜欢全局变量。


PPS. 以后这里不会再放ACM的代码了;感兴趣的话可以等河蟹在睡觉的某天访问 hi-if.blogspot.com 看看。

 

  1. #if 1 // includes
  2. #include <memory.h>
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <functional>
  6. using namespace std;
  7. #endif   //  for folding
  8. #define POJ_IS_STUPID 0
  9. #if     POJ_IS_STUPID
  10. #if 0
  11. struct state { //里面这些东西不一定都用得着倒是了
  12.     int sticks[51];  // 长度为 i 的木棍有 sticks[i] 个。
  13.     int figures[51]; // 各种长度
  14.     int nfigures;
  15.     int length;
  16.     int target;
  17.     int remained;
  18.     int max;
  19.     int min;
  20.     int sum;
  21. };
  22. template <class T>
  23. size_t inv_bin_search(T* array, size_t len, T const& n) {
  24.     size_t a=0,b=len,m1,m2=-1;
  25.     for (m1=(a+b)>>1;m1!=m2;) {
  26.         m2=m1;
  27.         if     (array[m1]==n) return m1;
  28.         else if (array[m1]>n)  a=m1;
  29.         else b=m1;
  30.         m1=(a+b)>>1;
  31.     }
  32.     if (array[m1]<n) return m1;
  33.     else return m1-1;
  34. }
  35. bool match(state& st, int target) {
  36.     bool first=(target==st.target);
  37.     int i,*j;
  38.     if (target>st.max) {
  39.         //for(i=st.max;i>=st.min;--i){
  40.         for (j=st.figures;i=*j;++j) {
  41.             if (st.sticks[i]) {
  42.                 --st.sticks[i];
  43.                 st.sum-=i;
  44.                 if (match(st,target-i))
  45.                     return true;
  46.                 st.sum+=i;
  47.                 ++st.sticks[i];
  48.                 if (first)
  49.                     return false;
  50.             }
  51.         }
  52.         return false;
  53.     } else if (target<st.min) {
  54.         return false;
  55.     } else if (target>st.sum) {
  56.         return false;
  57.     } else if (target==st.sum) {
  58.         return true;
  59.     }
  60.     if (st.sticks[target]) {
  61.         --st.sticks[target];
  62.         st.sum-=target;
  63.         if (--st.remained==0) return true;
  64.         if (match(st,st.target))
  65.             return true;
  66.         ++st.remained;
  67.         st.sum+=target;
  68.         ++st.sticks[target];
  69.         return false;
  70.     }
  71.     for (j=st.figures+inv_bin_search<int>(st.figures,st.nfigures,target);
  72.         *j>=target&&*j;++j);
  73.     for (;i=*j;++j) {
  74.         if (st.sticks[i]) {
  75.             --st.sticks[i];
  76.             st.sum-=i;
  77.             if (match(st,target-i))
  78.                 return true;
  79.             st.sum+=i;
  80.             ++st.sticks[i];
  81.             if (first)
  82.                 return false;
  83.         }
  84.     }
  85.     return false;
  86. }
  87. int main() {
  88.     for (state s={{0},{0},0,0};cin>>s.length&&s.length;) {
  89.         s.sum=0;
  90.         s.max=0;
  91.         s.min=100;
  92.         int x,i,j,n=0;
  93.         bool succeed=false;
  94.         for (i=0;i<=50;++i)
  95.             s.sticks[i]=0;
  96.         for (i=0;i<s.length;++i) {
  97.             cin>>x;
  98.             if (!s.sticks[x]) {
  99.                 s.figures[n]=x;
  100.                 ++n;
  101.             }
  102.             ++s.sticks[x];
  103.             s.sum+=x;
  104.             if (x>s.max) s.max=x;
  105.             if (x<s.min) s.min=x;
  106.         }
  107.         s.figures[n]=0;
  108.         s.nfigures=n;
  109.         sort(s.figures,s.figures+n,greater<int>());
  110.         for (j=s.max;j<=s.sum/2;++j) {
  111.             if (s.sum%j==0) {
  112.                 s.target=j;
  113.                 s.remained=s.sum/j;
  114.                 if ( match(s,j) ) {
  115.                     cout<<j<<endl;
  116.                     succeed=true;
  117.                     break;
  118.                 }
  119.             }
  120.         }
  121.         if (!succeed)
  122.             cout<<s.sum<<endl;
  123.     }
  124.     return 0;
  125. }
  126. #else
  127. struct state { //里面这些东西不一定都用得着倒是了
  128.     int sticks[51];  // 长度为 i 的木棍有 sticks[i] 个。
  129.     int figures[51]; // 各种长度
  130.     int nfigures;
  131.     int length;
  132.     int target;
  133.     int remained;
  134.     int max;
  135.     int min;
  136.     int sum;
  137. };
  138. template <class T>
  139. size_t inv_bin_search(T* array, size_t len, T const& n) {
  140.     size_t a=0,b=len,m1,m2=-1;
  141.     for (m1=(a+b)>>1;m1!=m2;) {
  142.         m2=m1;
  143.         if     (array[m1]==n) return m1;
  144.         else if (array[m1]>n)  a=m1;
  145.         else b=m1;
  146.         m1=(a+b)>>1;
  147.     }
  148.     if (array[m1]<n) return m1;
  149.     else return m1-1;
  150. }
  151. bool match(state& st, int target) {
  152.     int (&sticks)[51]=st.sticks;
  153.     int (&figures)[51]=st.figures;
  154.     int &sum=st.sum;
  155.     int &remained=st.remained;
  156.     bool first=(target==st.target);
  157.     int i,*j;
  158.     if (target>st.max) {
  159.         //for(i=st.max;i>=st.min;--i){
  160.         for (j=figures;i=*j;++j) {
  161.             if (sticks[i]) {
  162.                 --sticks[i];
  163.                 sum-=i;
  164.                 if (match(st,target-i))
  165.                     return true;
  166.                 sum+=i;
  167.                 ++sticks[i];
  168.                 if (first)
  169.                     return false;
  170.             }
  171.         }
  172.         return false;
  173.     } else if (target<st.min) {
  174.         return false;
  175.     } else if (target>st.sum) {
  176.         return false;
  177.     } else if (target==st.sum) {
  178.         return true;
  179.     }
  180.     if (sticks[target]) {
  181.         --sticks[target];
  182.         sum-=target;
  183.         if (--remained==0) return true;
  184.         if (match(st,st.target))
  185.             return true;
  186.         ++remained;
  187.         sum+=target;
  188.         ++sticks[target];
  189.         return false;
  190.     }
  191.     for (j=figures+inv_bin_search<int>(figures,st.nfigures,target);
  192.         *j>=target&&*j;++j);
  193.     for (;i=*j;++j) {
  194.         if (sticks[i]) {
  195.             --sticks[i];
  196.             sum-=i;
  197.             if (match(st,target-i))
  198.                 return true;
  199.             sum+=i;
  200.             ++sticks[i];
  201.             if (first)
  202.                 return false;
  203.         }
  204.     }
  205.     return false;
  206. }
  207. int main() {
  208.     for (state s={{0},{0},0,0};cin>>s.length&&s.length;) {
  209.         s.sum=0;
  210.         s.max=0;
  211.         s.min=100;
  212.         int x,i,j,n=0;
  213.         bool succeed=false;
  214.         for (i=0;i<=50;++i)
  215.             s.sticks[i]=0;
  216.         for (i=0;i<s.length;++i) {
  217.             cin>>x;
  218.             if (!s.sticks[x]) {
  219.                 s.figures[n]=x;
  220.                 ++n;
  221.             }
  222.             ++s.sticks[x];
  223.             s.sum+=x;
  224.             if (x>s.max) s.max=x;
  225.             if (x<s.min) s.min=x;
  226.         }
  227.         s.figures[n]=0;
  228.         s.nfigures=n;
  229.         sort(s.figures,s.figures+n,greater<int>());
  230.         for (j=s.max;j<=s.sum/2;++j) {
  231.             if (s.sum%j==0) {
  232.                 s.target=j;
  233.                 s.remained=s.sum/j;
  234.                 if ( match(s,j) ) {
  235.                     cout<<j<<endl;
  236.                     succeed=true;
  237.                     break;
  238.                 }
  239.             }
  240.         }
  241.         if (!succeed)
  242.             cout<<s.sum<<endl;
  243.     }
  244.     return 0;
  245. }
  246. #endif
  247. #else
  248. #if 0 //以前的
  249. struct state { //不想用全局变量, 又不应该在递归的函数中使用太多参数, so...
  250.     int  sticks[65];
  251.     bool thereis[65];
  252.     int  length;
  253.     int  sum;
  254.     int  max;
  255.     int  target;
  256. };
  257. bool dfs(state& st, int target, int nremained, int begin=0) {
  258.     if ( target==0 ) {
  259.         if ( nremained==1 )
  260.             return true;
  261.         else
  262.             return dfs(st,st.target,nremained-1,1);
  263.     } else {
  264.         if (begin>=st.length)
  265.             return false;
  266.         bool first=(target==st.target),last=false;
  267.         for (int i=begin;i<st.length;++i) {
  268.             if (!st.thereis[i])
  269.                 continue;
  270.             if (st.sticks[i]>target) {
  271.                 // if(first){return false;}//impossible
  272.                 continue;
  273.             }
  274.             st.thereis[i]=false;
  275.             last=(st.sticks[i]==target);
  276.             if (dfs(st,target-st.sticks[i],nremained,i+1)) {
  277.                 return true;
  278.             } else {
  279.                 st.thereis[i]=true;
  280.                 if ( first||last ) return false;
  281.                 for (;st.sticks[i]==st.sticks[++i];);
  282.                 --i;
  283.             }
  284.         }
  285.     }
  286.     return false;
  287. }
  288. int main() {
  289.     for (state s;cin>>s.length&&s.length;) {
  290.         s.max=s.sum=0;
  291.         int x;
  292.         bool succeed=false;
  293.         for (int i=0;i<s.length;++i) {
  294.             cin>>x;
  295.             s.sticks[i]=x;
  296.             s.sum+=x;
  297.             if (x>s.max) s.max=x;
  298.             s.thereis[i]=true;
  299.         }
  300.         sort(s.sticks,s.sticks+s.length,greater<int>());
  301.         s.sticks[s.length]=0;
  302.         s.thereis[s.length]=false;
  303.         for (int j=s.max;j<=s.sum/2;++j) {
  304.             if (s.sum%j==0) {
  305.                 s.target=j;
  306.                 if ( dfs(s,j,s.sum/j) ) {
  307.                     cout<<j<<endl;
  308.                     succeed=true;
  309.                     break;
  310.                 }
  311.             }
  312.         }
  313.         if (!succeed)
  314.             cout<<s.sum<<endl;
  315.     }
  316.     return 0;
  317. }
  318. #else
  319. int  g_sticks[65];
  320. bool g_used[65];
  321. int  g_length;
  322. int  g_sum;
  323. int  g_max;
  324. int  g_min;
  325. int  g_target;
  326. bool dfs(int target, int remained, int begin) {
  327.     if( target<g_min||begin>=g_length )
  328.         return false;
  329.     if (target==g_target) { //第一根
  330.         for (int i=begin;i<g_length;++i) {
  331.             if (g_used[i])
  332.                 continue;
  333.             g_used[i]=true;
  334.             if(g_sticks[i]==target){ // 最后一根
  335.                 if(remained==1)
  336.                     return true;
  337.                 if(dfs(g_target , remained-1, 1))
  338.                     return true;
  339.                 g_used[i]=false;
  340.                 return false;
  341.             } else if (dfs(target-g_sticks[i],remained,i+1))
  342.                 return true;
  343.             g_used[i]=false;
  344.             return false;
  345.         }
  346.     } else {
  347.         for (int i=begin;i<g_length;++i) {
  348.             if (g_used[i])
  349.                 continue;
  350.             if (g_sticks[i]>target)
  351.                 continue;
  352.             g_used[i]=true;
  353.             if(g_sticks[i]==target){ // 最后一根
  354.                 if(remained==1)
  355.                     return true;
  356.                 if(dfs(g_target , remained-1, 1))
  357.                     return true;
  358.                 g_used[i]=false;
  359.                 return false;
  360.             }
  361.             if (dfs(target-g_sticks[i],remained,i+1))
  362.                 return true;
  363.             g_used[i]=false;
  364.             for(;g_sticks[i]==g_sticks[i+1];++i);
  365.         }
  366.     }
  367.     return false;
  368. }
  369. //#include <fstream>
  370. int main() {
  371.     //ifstream fin("test.txt");
  372.     istream& xin=cin;//fin;
  373.     for (;xin>>g_length&&g_length;) {
  374.         int x;
  375.         bool succeed=false;
  376.         g_max=g_sum=0;
  377.         g_min=1000;
  378.         for (int i=0;i<g_length;++i) {
  379.             xin>>x;
  380.             g_sticks[i]=x;
  381.             g_sum+=x;
  382.             if (x>g_max) g_max=x;
  383.             if (x<g_min) g_min=x;
  384.             g_used[i]=false;
  385.         }
  386.         sort(g_sticks,g_sticks+g_length,greater<int>());
  387.         g_sticks[g_length]=0;
  388.         g_used[g_length]=true;
  389.         for (int j=g_max;j<=g_sum/2;++j) {
  390.             if (g_sum%j==0) {
  391.                 g_target=j;
  392.                 if ( dfs(j,g_sum/j,0) ) {
  393.                     cout<<j<<endl;
  394.                     succeed=true;
  395.                     break;
  396.                 }
  397.             }
  398.         }
  399.         if (!succeed)
  400.             cout<<g_sum<<endl;
  401.     }
  402.     return 0;
  403. }
  404. #endif
  405. #endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值