Title: EOJ1981 | | POJ1011 Classic dfs+ pruning + bizarre Data
Description
George took sticks of the same length and cut them randomly until all partsbecame at most units long. Now he wants to return sticks to the originalstate, but he forgot how many sticks he had originally
Input
The input contains blocks of 2 lines. The first line contains the number ofsticks parts after cutting, there is at most sticks. The second linecontains the lengths of those parts separated by the space. The last line ofthe file contains zero.
Output
The output should contains the smallest possible length of original sticks, Oneper line.
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5
Topic Analysis:
The shortest stick lengths of the same length can be spelled out with n sticks.
Ideas for DFS recursive enumeration of each stick, the main optimization is the pruning techniques are: 1. After sorting from large to small enumeration of each stick, because each stick will be used, priority selection of large can reduce the recursion depth.
2. The length of the stick to be spelled is approximate to the total length.
3, if the same length of the stick is not selected before, then no longer consider this stick.
4, if cannot spell the length <=SUM/2 the small stick, then can only spell the length is the SUM the small stick.
5, if the remaining first stick cannot be used, it means that the task cannot be completed before the DFS can be terminated, because each stick will be used.
6, if the stick length is the length of the current small stick, it means that the stick is the last small stick. If you are unable to complete the task by selecting the current small stick, the small stick cannot be used, and the program can be terminated prematurely.
Do the above several pruning can pass POJ, time is 16MS. But can not pass the time limit of 5000ms on the Eoj, refer to the net limit the recursive call depth can pass, but think of feeling just to pass through, no reason.
Version one: No recursion depth limit can be obtained by poj1011
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace Std;
BOOL VIS[65];
int A[65],n,sum,each;
BOOL CMP (const int &A,CONST int &b) {
Return a>b;
}
BOOL Dfs (int m,int left) {
if (m==0 &&left==0) {
return true;
}
if (!left) Left=each;
int i;
for (I=0;i<n;++i) {
if (i>0&& a[i]==a[i-1] &&!vis[i-1]) continue;
if (vis[i]| | a[i]>left) continue;
Vis[i]=true;
if (Dfs (m-1,left-a[i)))
Returntrue;
else{
Vis[i]=false;
if (a[i]==left| | left==each)
Returnfalse;
}
}
return false;
}
int main ()
{
while (scanf ("%d", &n), N) {
sum=0;
for (Inti=0;i<n;++i) {
scanf ("%d", &a[i]);
Sum+=a[i];
}
Sort (a,a+n,cmp);
int i;
for (I=a[0];i<=sum/2;++i) {
if (sum%i) continue;
memset (vis,false,sizeof (VIS));
Each=i;
if (Dfs (N,each)) {
printf ("%d\n", I);
Break
}
}
if (I>SUM/2) printf ("%d\n", sum);
}
return 0;
}
Version two: The number of recursive calls is added in order to pass Eoj
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace Std;
BOOL VIS[65];
int a[65],n,sum,each,deep;
BOOL CMP (const int &a,const int&b) {
Return a>b;
}
BOOL Dfs (int m,int left) {
if (deep++>200000) return false;
if (m==0 && left==0) {
return true;
}
if (!left) Left=each;
int i;
for (I=0;i<n;++i) {
if (i>0 && a[i]==a[i-1] &&!vis[i-1]) continue;
if (Vis[i] | | a[i]>left) continue;
Vis[i]=true;
if (Dfs (m-1,left-a[i)))
return true;
else{
Vis[i]=false;
if (A[i]==left | | left==each)
return false;
}
}
return false;
}
int main ()
{
while (scanf ("%d", &n), N) {
sum=0;
for (int i=0;i<n;++i) {
scanf ("%d", &a[i]);
Sum+=a[i];
}
Sort (a,a+n,cmp);
int i;
for (I=a[0];i<=sum/2;++i) {
if (sum%i) continue;
memset (vis,false,sizeof (VIS));
Each=i;
Deep=0;
if (Dfs (N,each)) {
printf ("%d\n", I);
Break
}
}
if (I>SUM/2) printf ("%d\n", sum);
}
return 0;
}
EOJ1981 | | POJ1011 Classic dfs+ pruning + bizarre Data