ideas
Binary + search + pruning.
First, an answer is divided into two parts, which means that at most x blocks can be cut out. (A conclusion: the cut must be from the smaller first x block. If one wood can meet many needs, then cutting the smallest one means more opportunities for future selection.)
Then brute-force search for which wood the first x blocks are cut from.
Pruning 1: If all the wood provided can't meet the required wood, just skip it
Pruning 2: Record the wasted wood (that is, after a piece of wood is cut off, even the smallest of the remaining wood cannot be cut out), if the total amount of wood provided - wasted < all current wood If necessary, just skip it.
Pruning 3: The current required wood is the same length as the next required piece of wood, so there is no need to start the search from the first piece, but directly from the last searched place.
Code:
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 5 using namespace std; 6 7 const int N = 10010; 8 int n,m,rest,tot; 9 int a[N],b[N],c[N],sum[N]; 10 11 inline int read() { 12 int x = 0,f = 1;char ch = getchar(); 13 for (; !isdigit(ch); ch=getchar()) if(ch=='- ' ) f=- 1 ; 14 for (; isdigit(ch); ch=getchar()) x=x* 10 +ch- ' 0 ' ; 15 return x * f; 16 } 17 bool dfs( int now, int s) { // The currently needed wood, starting from the sth wood given 18 if (!now) return true ; 19 if (rest+sum[now] > tot) return false ; // pruning 2 20 for ( int i=s; i<=m; ++i) {// enumerate all given wood 21 if (c[i] >= b[now]) { // current wood can cut out required 22 c[i] -= b[now]; // - 23 if (c[i] < b[ 1 ]) rest += c[i]; 24 if (b[now]==b[now- 1 ]) { 25 if (dfs(now- 1 ,i)) return true ; 26 } 27 else { if (dfs(now- 1 , 1 )) return true ;} // prune 3 28 if (c[i] < b[1]) rest -= c[i]; 29 c[i] += b[now]; // - 30 } 31 } 32 return false; 33 } 34 bool check(int x) { 35 for (int i=1; i<=m; ++i) c[i] = a[i]; 36 rest = 0; 37 return dfs(x,1); 38 } 39 int main() { 40 m = read(); 41 for (int i=1; i<=m; ++i) a[i] = read(),tot += a[i]; 42 sort(a+1,a+m+1); 43 n = read(); 44 for (int i=1; i<=n; ++i) b[i] = read(); 45 sort(b+1,b+n+1); 46 for (int i=1; i<=n; ++i) sum[i] = sum[i-1] + b[i]; 47 48 while (sum[n] > tot) n--; // prune 1 49 int L = 0 ,R = n,ans; // L has a case where it is equal to 0! 50 while (L <= R) { 51 int mid = (L + R) / 2 ; 52 if (check(mid)) L = mid + 1 ,ans = mid; 53 else R = mid - 1 ; 54 } 55 cout << ans << ' \n ' ; 56 return 0 ; 57 }