搜索--子集和

来源:互联网 发布:司南阁淘宝找不到 编辑:程序博客网 时间:2024/05/14 15:40

一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值

  比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1;  

  {3,6}{2,4,3} m=2

  {3,3}{2,4}{6} m=3 所以m的最大值为3

解:poj 1011,搜索+强剪枝

Description

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero. 
 Output

The output should contains the smallest possible length of original sticks, one per line. 

http://hi.baidu.com/zldiablo/blog/item/df04bcd95e6774ec38012f22.html
http://www.cppblog.com/rakerichard/archive/2010/01/14/105685.html
1、设所有木棍的长度和是sum,那么原长度(也就是输出)一定能被sum整除,不然就没法拼了。
2、原来的长度一定大于等于所有木棍中最长的那个
    因此可以从最长的长度开始,枚举每个能被sum整除的长度,因为要求最小的长度,所以搜到第一个就是结果了。
    遍历的过程就是设定一个bool的数组保存每个木棍是不是被用到过,然后用深度优先搜索,判断每个木棍选或者不选看能不能得到结果。或者说是使用给定的木棍,能不能拼出sum/L个长度是L的木棍。而搜索过程也就是一个一个的去拼长度是L的木棍。

#include <iostream>#include <cstring>#include <algorithm>#include <functional>#include <stdio.h>using namespace std;const int N=64;int stick[N];bool used[N];int num;bool DFS(int unused,int rest,int tgtLen)//要使得组合成stNum组,每个组之和为tgtLen;rest表示第i个组还差rest长度就等于tgtLen{if(unused ==0 && rest ==0)return true;if(rest ==0)//上一组已经凑够tgtLen,这一组要重新凑tgtLenrest = tgtLen;for (int i = 0;i<num;++i){if(used[i])continue;if(stick[i]>rest)continue;used[i] = true;if(DFS(unused - 1,rest - stick[i],tgtLen))return true;used[i] = false;//在这一组还剩余rest的情况下不能满足条件则,if(stick[i]==rest || rest == tgtLen)//如果在一个组刚开始凑的时候,stick[i]放进去,就导致无解,就说明只要有stick[i]在,就不能有解;break; }return false;}int main(){while (scanf("%d",&num) && num){memset(used,0,sizeof(used));int score =0;for(int i=0;i<num;++i){scanf("%d",stick+i);score +=stick[i];}sort(stick,stick+num,greater<int>());for (int stNum = num;stNum>=1;--stNum){if(score %stNum ==0 && (score/stNum)>=stick[0])if(DFS(num,score/stNum,score/stNum))cout<<score/stNum<<endl;}}return 0;}



原创粉丝点击