• [BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】


    题目链接:BZOJ - 1082

    题目分析

    二分 + DFS验证。

    二分到一个 mid ,验证能否选 mid 个根木棍,显然要选最小的 mid 根。

    使用 DFS 验证,因为贪心地想一下,要尽量先用提供的小的木木棍,尽量先做出需要的大的木棍,所以要先将提供的木棍和需要的木棍都排序。

    DFS 的时候是按照需要的木棍从大到小的顺序一层一层搜,每一层上是按照从小到大的顺序枚举提供的木棍。(当然枚举的时候已经不一定是从小到大了,有些木棍已经被截掉了一些。)

    要使用两个有效的剪枝:

    1)如果下一层的木棍和这一层的木棍等长,就从这一层木棍枚举到的提供的木棍开始枚举,因为前面的都是不可以的。

    2)当一根木棍被截掉一段之后小于最小的需要的木棍,那么它就废掉了,记录当前废掉的木棍总长Rest,如果Rest + 1到mid所有木棍的总长 > 提供的所有木棍总长,那么就返回 false。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    
    const int MaxM = 50 + 5, MaxN = 1000 + 5;
    
    int n, m, Ans, Rest, Need, Tot;
    int A[MaxM], B[MaxN], Sum[MaxN];
    
    bool DFS(int x, int y)
    {
    	if (Rest + Need > Tot) return false;
    	bool ret = false;
    	for (int i = y; i <= m; ++i) 
    	{
    		if (A[i] >= B[x]) 
    		{
    			A[i] -= B[x];
    			if (A[i] < B[1]) Rest += A[i];
    			if (x == 1) ret = true;
    			else if (B[x - 1] == B[x]) ret = DFS(x - 1, i); 
    			else ret = DFS(x - 1, 1); 
    			Rest -= A[i]; 
    			A[i] += B[x];
    			if (ret) return true;
    		}
    	}
    	return false;
    }
    
    int main() 
    {
    	scanf("%d", &m);
    	for (int i = 1; i <= m; ++i) scanf("%d", &A[i]);
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i) scanf("%d", &B[i]);
    	sort(A + 1, A + m + 1);
    	for (int i = 1; i <= m; ++i) Tot += A[i];
    	sort(B + 1, B + n + 1);
    	for (int i = 1; i <= n; ++i) Sum[i] = Sum[i - 1] + B[i];
    	int l, r, mid;
    	l = 0; r = n;
    	Ans = 0;
    	while (l <= r) 
    	{
    		mid = (l + r) >> 1;
    		Need = Sum[mid];
    		Rest = 0;
    		if (DFS(mid, 1)) 
    		{
    			Ans = mid;
    			l = mid + 1;
    		}
    		else r = mid - 1;
    	}
    	printf("%d
    ", Ans);
    	return 0;
    }
    

      

  • 相关阅读:
    template
    open File Browser in shell
    自定义模板类型vs模板类型自动推测
    protobuffer
    多重继承&虚继承
    What I'm Researching
    JobTracker和TaskTracker
    MapReduce
    How To Use Google Flags
    Frequently Used Shell Commands
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4319687.html
Copyright © 2020-2023  润新知