http://poj.org/problem?id=1011
To divide the given set into several sets, each set is equal to ans, and ans is the smallest because this and ans are only within [1,64*50], so you can use DFS as a test
First, ANS needs to meet two conditions 1. Can be divided by the sum of the total set of 2. is a subset of the total set and for the condition 1, you can pass the test to traverse for condition 2, can be pre-filtered by DP, both of which take a little time
Then the search can be divided into sets of the sum of a few sets of ans,
1. Can be found from large to small, because the larger is not flexible, and all the elements need to take
2. For example, for 5,4,2,2,1 using the first 2, looking down, no answer, not the first 2, no need to find a second, the third 2
If you've looked for the same number before, then you won't have to look for the same number.
3. If this number is exactly a combination of ans, then it can be composed of the remaining numbers, that is, a new set and the ANS, the remaining can be composed of several and the set of ans to take ans, or not to take ans
#include <cstdio> #include <cstring> #include <algorithm>using namespace std;int a[64],n;bool cmp (int A,int b) {return a>b;} BOOL Reachable[64*51];bool used[64];bool dfs (int s,int tmp,int sub) {//printf ("s:%d tmp:%d sub:%d\n", s,tmp,sub); Used[s]=true; Tmp+=a[s]; if (tmp>sub) {//cannot appear puts ("ERROR"); Used[s]=false; return false; } if (tmp==sub) {//is exactly one and the set for ans (int i=0;i<n;i++) {if (!used[i]) { if (Dfs (i,0,sub)) return True;//dfs a new collection, directly returning the remaining elements can be combined into several and a set of ans for the El se {used[s]=false; return false; }}}} return true;//all elements have been used} int f=-1; for (int i=s+1;i<n;i++) {if (f==a[i]| | Used[i]) {Continue;} If this function of this state has already looked for the same number if (tmp+a[i]==sub) {///return the remaining elements directly in the combined state if (DFS (i,tmp,sub)) return TR Ue else {used[s]=false; return false; }} else if (tmp+a[i]<sub) {//can try to add into this set if (Dfs (i,tmp,sub)) return T Rue } F=a[i]; } Used[s]=false; return false;} int main () {while (scanf ("%d", &n) ==1&&n) {int sum=0,mx=0; memset (reachable,false,sizeof (reachable)); for (int i=0;i<n;i++) {scanf ("%d", a+i); Sum+=a[i]; Mx=max (A[I],MX); } reachable[a[n-1]]=true; Reachable[0]=true; Sort (a,a+n,cmp);//from large to small search for (int i=n-2;i>=0;i--) {for (int J=0;j<sum&&j+a[i]<=sum;j++) {if (Reachable[j]) { Reachable[j+a[i]]=true;//reachable[i]=true I can be added and obtained by certain elements in the total set} }} bool Fnd=false; for (int i=mx;i<sum;i++) {if (Sum%i==0&&reachable[i]) {MEMS ET (used,0,sizeof (used)); if (Dfs (0,0,i)) {printf ("%d\n", I); Fnd=true; Break }}} if (!FND) printf ("%d\n", sum); } return 0;}
POJ 1011 Sticks Dfs, pruning difficulty: 2