最近做做搜索题吧。。。^_^
然后又被虐了。。。T T
这还是一道usaco题。。。我去。。。
为了方便叙述,FJ买的叫"木块",要被切掉的叫"木材"!!!(我也是醉了0.0)
根据贪心,我们肯定先搞到小的木块。。。于是先对要买的木块进行排序,然后二分答案
之后如何判断:
裸的dfs肯定过不掉T T,考虑优化
(1)如果两块木块长度相同,第一个已经被dfs过了且从第x块木材上被切下来,则第二个也至少要从第x块木材上切。(貌似是对称性原理的说。。。)
(2)某巨巨:"用waste表示每一个已经裁过的木材浪费的木材和,所谓浪费的木材就是最小的木块都比它大,那么他当前就已经裁不出任何木块了。就把这个木材加到waste去,如果waste>木材和-s[mid],说明这样裁木材是错误的,所以减枝。"
两个优化使得搜索速度快的飞起!!!
1 /************************************************************** 2 Problem: 1082 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:4 ms 7 Memory:820 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 using namespace std; 15 const int N = 1005; 16 int n, m, waste, l, r, mid; 17 int a[N], b[N], c[N], s[N], T; 18 19 inline int read(){ 20 int x = 0; 21 char ch = getchar(); 22 while (ch < '0' || ch > '9') 23 ch = getchar(); 24 25 while (ch >= '0' && ch <= '9'){ 26 x = x * 10 + ch - '0'; 27 ch = getchar(); 28 } 29 return x; 30 } 31 32 bool dfs(int x, int pos){ 33 if (!x) return 1; 34 if (s[mid] + waste > T) return 0; 35 for (int i = pos; i <= m; ++i) 36 if (c[i] >= b[x]){ 37 c[i] -= b[x]; 38 if (c[i] < b[1]) 39 waste += c[i]; 40 if (b[x] == b[x - 1]){ 41 if (dfs(x - 1, i)) 42 return 1; 43 } 44 else if (dfs(x - 1, 1)) return 1; 45 if (c[i] < b[1]) waste -= c[i]; 46 c[i] += b[x]; 47 } 48 return 0; 49 } 50 51 int main(){ 52 m = read(); 53 for (int i = 1; i <= m; ++i) 54 a[i] = read(), T += a[i]; 55 n = read(); 56 for (int i = 1; i <= n; ++i) 57 b[i] = read(); 58 sort(a + 1, a + m + 1); 59 sort(b + 1, b + n + 1); 60 for (int i = 1; i <= n; ++i) 61 s[i] = s[i - 1] + b[i]; 62 while (s[n] > T) --n; 63 l = 0, r = n + 1; 64 while (l + 1 < r){ 65 waste = 0; 66 memcpy(c, a, sizeof(a)); 67 mid = l + r >> 1; 68 if (dfs(mid, 1)) l = mid; 69 else r = mid; 70 } 71 printf("%d ", l); 72 return 0; 73 }