if(stick[i]==temp||temp==len) break;这个剪枝的理解:
stick[i]==temp:
表示前面的N根木棒拼接成功了,但是后面剩下的拼接失败了,说明就要去掉以前恰好合适的木棒,而用其他的小于等于它的其他木棒来代替他,
其他成功代替它的木棍,都是小于等于它的,它们拼接的自由度更大都使剩下的木棍拼接失败了,换了,最终还是会失败,所以直接剪枝了;
temp==len:
开始拼接一根新的木棍时,第一根肯定不会小于其他没有用过的木棍了,(由于降序排序了的,并且每次都是从长的开始找起的),那么这根最长
的和剩下的所有的木棍拼接都失败了,但是最终要拼接成功,那么这个最长的木棍是一定要被用掉的,但是从目前的状况来看无论如何也用不掉了
所以拼接最终会失败的,因此后面的都不用尝试了。
直接跳出循环,返回false。
以下是AC代码:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<cstdlib> #include<queue> #define MAXN 100 #define LL long long int using namespace std; int cmp(const void *a,const void *b){ return *(int *)b-*(int *)a; } int stick[70]; bool use[70]; bool is_original(int totalsticks,int unusedsticks,int temp,int len){ if(unusedsticks==0&&temp==0) return true; if(temp==0) temp=len; for(int i=0;i<totalsticks;i++){ if(use[i]==false) continue; if(stick[i]>temp) continue; use[i]=false; if(is_original(totalsticks,unusedsticks-1,temp-stick[i],len)){ return true; } use[i]=true; if(stick[i]==temp||temp==len) break; } return false; } int main(){ int n; while(~scanf("%d",&n),n){ int sum=0; memset(use,true,sizeof(use)); for(int i=0;i<n;i++){ scanf("%d",&stick[i]); sum+=stick[i]; } qsort(stick,n,sizeof(stick[0]),cmp); int len=stick[0]; for(int i=len;i<=sum;i++){ if(sum%i!=0) continue; if(is_original(n,n,0,i)){ printf("%d\n",i); break; } } } return 0; }