經歷了各種TLE,各種WA,還有一次RE,終于在網上找到兩句至理名言,靠這兩個剪枝,在北大上AC了這道錯了25次的1011.
但不行的是在Hdu,依然WA中,預知后事如何,請聽下回分解。
強大的剪枝!1.搜索每根大木棍的時候,如果因為安放了第一段木棍就無法提供合理解的時,就不用去試探其他小木棍在第一段位置的情況了。所以回溯到上一個大木棍的搜索,是第一個大木棍的第一段出現問題,那么該長度肯定不符合要求。
2.每個大木棍的最后一段,如果不合要求,那么也不用去試圖去安放其他的小木棍了,直接回溯到上段木棍即可。因為,換成更小的木棍,即便也可使木棍填滿,小木棍也有可能在將來的時候無法安放。簡單的說,如果它不行,采用別的更小的木棍也不行;如果它可以,采用別的更小的木棍也一定可以。
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int a[100],n,sum, get, mark[100];
int cmp(int c, int b)
{
return c>b;
}
int dfs(int nowlen, int nowget, int nowi)
{
for(int i=nowi; i<n; i++)
if(mark[i]==0 && nowlen>=a[i]){
mark[i]=1;
if(nowlen>a[i]){
if(dfs(nowlen-a[i], nowget, i+1)==1)
return 1;
else if(nowlen==sum/get) //剪枝1
{ mark[i]=0; return 0; }
}
else if(nowlen==a[i]){
if(nowget+1==get) return 1;
if(dfs(sum/get, nowget+1, 0)==1)
return 1;
else{
mark[i]=0;//剪枝2
return 0;
}
}
mark[i]=0;
}
return 0;
}
int main()
{
int i,j,k;
while(scanf("%d",&n) && n){
sum=0;
memset(a, 0, sizeof(a));
for(i=0; i<n; i++){
scanf("%d",&a[i]);
sum+=a[i];
}
sort(a, a+n, cmp);
get=sum/a[0];
while(sum%get!=0){
get--;
}
while(1){
memset(mark, 0, sizeof(mark));
if(dfs(sum/get, 0, 0)==1)
break;
else{
get--;
while(sum%get!=0){
get--;
}
}
}
printf("%d\n",sum/get);
}
return 0;
}