1082: [SCOI2005] Fence

Link

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 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324937651&siteId=291194637