1. 程式人生 > >POJ - 1011 剪枝練習

POJ - 1011 剪枝練習

長度 turn break pri fail spa 減少 n) ans

題意:給定n條拆掉的棍子,問能湊成最短的多條相同長度棍子的最短長度
x:當前第幾條正在合成的棍子
y:目前正在嘗試的拆掉的棍子
z:當前長度
剪枝方案:
1.按照長度單調性排序,減少重復搜索
2.如果當前拼接棍子失敗,那接下來相同長度也會失敗
3.第一條棍子就失敗就不必搜索了

/*H E A D*/
int a[666],tot,ans,sum,n;
bool used[666];
bool dfs(int x,int y,int z){
    if(x==tot+1) return 1;
    if(z==sum/tot)  return dfs(x+1,1,0);
    if(y==n+1) return
0; int failed=0;//!!! rep(i,y,n){ if(!used[i]&&z+a[i]<=sum/tot&&failed!=a[i]){ used[i]=1; if(dfs(x,y+1,z+a[i])) return 1; failed=a[i]; used[i]=0; if(z==0)return 0;//!!! } } return 0; } int main(){ while
(~iin(n)){ if(n==0)break; rep(i,1,n) a[i]=read(); sort(a+1,a+1+n,greater<int>()); sum=0; rep(i,1,n) sum+=a[i]; ll ans=oo; rrep(i,sum,1){ if(sum%i==0){ tot=i; memset(used,0,sizeof used); if
(dfs(1,1,0)){ ans=min(ans,(ll)sum/tot); break; } } } println(ans); } return 0; } int main(){ while(~iin(n)){ if(n==0)break; rep(i,1,n) a[i]=read(); sort(a+1,a+1+n,greater<int>()); sum=0; rep(i,1,n) sum+=a[i]; ll ans=oo; rrep(i,sum,1){ if(sum%i==0){ tot=i; flag=0; memset(used,0,sizeof used); if(dfs(1,1,0)){ ans=min(ans,(ll)sum/tot); break; } } } println(ans); } return 0; }

POJ - 1011 剪枝練習