P1120 小木棍 [資料加強版]
阿新 • • 發佈:2020-09-13
連結Miku
程式碼參考:小藍書
暴力很好寫,可惜過不了,怎麼辦,剪枝起飛。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n; int len[500001]; int fl[500001]; int sum; int li; int cnt; int maxx=0; int ans[500001]; bool dfs(int now,int l,int ord){ if(now>cnt)//over return 1; if(l==maxx) return dfs(now+1,0,1);//開始下一個 int fail=0; for(int i=ord;i<=n;++i){ if(!fl[i]&&l+len[i]<=maxx&&fail!=len[i]){//因為是從大到小放的 //所以說如果不行的話肯定同樣長度的都不行 fl[i]=1; if(dfs(now,l+len[i],i+1)) return 1; fail=len[i]; fl[i]=0; //不好理解的剪枝 //l==0的部分是因為如果此木棍出現在新木棍中不可行的話,那麼它出現在之後任何一個新木棍的結果都是一樣的--不行 //後半段同理,貪心的考慮一下,一整根木棍都不行的話,就算用幾根小木棍拼起來也沒有意義 if(l==0||l+len[i]==maxx) return 0; } } return 0; } bool cmp(int x,int y){ return x>y; } int main(){ scanf("%d",&n); sum=0; maxx=0; int xiu; int lll=0; for(int i=1;i<=n;++i){ scanf("%d",&xiu); if(xiu>50)//自動忽略 continue; len[++lll]=xiu; sum+=len[lll]; maxx=max(maxx,len[lll]); } n=lll; sort(len+1,len+n+1,cmp); //從大到小搞啊 int i; for( ;maxx<=sum;++maxx){ if(sum%maxx) continue; //顯然只有原長是總長的因數才有意義 cnt=sum/maxx; memset(fl,0,sizeof(fl)); if(dfs(1,0,1)){ break; } } cout<<maxx<<endl; return 0; }