[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1082
[算法]
首先二分“最多得到的符合条件的木板数”,检验时可以使用DFS,但是,我们需要进行一下两点剪枝
1. 如果当前木板的长度等于后一块木板的长度,那么下一次搜索只需从这一次进行搜索的位置开始搜即可
2. 如果当前浪费的木板总长度 > 提供木板长度总和 - 需要得到的木板的总长度,那么显然是不可行的
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXM 55 #define MAXN 1010 int i,n,m,l,r,ans,mid,total,w; int a[MAXM],b[MAXN],cnt[MAXN]; inline bool dfs(int dep,int last) { int i,pos; bool flag = false; if (dep == 0) return true; if (w > total - cnt[mid]) return false; for (i = last; i <= m; i++) { if (a[i] >= b[dep]) { a[i] -= b[dep]; if (a[i] < b[1]) w += a[i]; if (b[dep - 1] == b[dep]) flag = dfs(dep - 1,i); else flag = dfs(dep - 1,1); if (a[i] < b[1]) w -= a[i]; a[i] += b[dep]; if (flag) return true; } } return false; } inline bool check(int m) { w = 0; if (dfs(m,1)) return true; else return false; } int main() { scanf("%d",&m); for (i = 1; i <= m; i++) { scanf("%d",&a[i]); total += a[i]; } scanf("%d",&n); for (i = 1; i <= n; i++) scanf("%d",&b[i]); sort(a+1,a+m+1); sort(b+1,b+n+1); for (i = 1; i <= n; i++) cnt[i] = cnt[i - 1] + b[i]; l = 1; r = n; while (l <= r) { mid = (l + r) >> 1; if (check(mid)) { ans = mid; l = mid + 1; } else r = mid - 1; } printf("%d ",ans); return 0; }