這個題真的是太nb了,各種騷

二分答案,肯定要減最小的mid個,從大往小搜每一個木板,從大往小列舉所用的木材

噹噹前木材比最短的木板還短,就扔到垃圾堆裡,並記錄waste,當 waste+sum>tot 時,return

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<cmath>
  6. #define N 2005
  7. using namespace std;
  8. int n,m,w[N],nd[N],ans,ANS,sum[N],tt;
  9. void dfs(int x,int y,int wst,int mid){
  10. if(wst+sum[mid]>tt)return;
  11. if(y<=0){ans=1;return;}
  12. for(int i=x;i<=n;i++){
  13. if(w[i]>=nd[y]){
  14. w[i]-=nd[y];
  15. if(w[i]<nd[1]) wst+=w[i];
  16. if(nd[y]==nd[y-1]) dfs(i,y-1,wst,mid);
  17. else dfs(1,y-1,wst,mid);
  18. if(w[i]<nd[1]) wst-=w[i];
  19. w[i]+=nd[y];
  20. if(ans==1)return;
  21. }
  22. }
  23. }
  24. bool da(int a,int b){return a>b;}
  25. int main(){
  26. //freopen("fence8.in","r",stdin);
  27. //freopen("fence8.out","w",stdout);
  28. scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&w[i]),tt+=w[i];
  29. scanf("%d",&m); for(int i=1;i<=m;i++)scanf("%d",&nd[i]);
  30. sort(w+1,w+n+1,da);sort(nd+1,nd+m+1);
  31. for(int i=1;i<=m;i++)sum[i]=sum[i-1]+nd[i];
  32. int l=0,r=m,mid;
  33. while(l<=r){
  34. mid=(l+r)>>1;
  35. ans=0;dfs(1,mid,0,mid);
  36. if(ans){ANS=mid;l=mid+1;}
  37. else r=mid-1;
  38. }
  39. printf("%d\n",ANS);
  40. return 0;
  41. }