这个讲的超好....一定要看...然后看我代码就好懂啦...
各种优化确实非常好....搜索的一道好题...
挂代码:
/* Problem : USACO 4.1.2 栅栏的木料 Author : Robert Yuan 优化解释: 0. 二分+贪心判断可行解 (根据自己设计的贪心算法尽量的得到一个比较靠近正确值的 ans,再后面的搜索的下界就会大大提高) 1. 如果使用的木料与上一块的木料大小相同,那么上一块若没有选前 i块木板,这一块也不要选(1.若是因为前面的太小而不选,那么对于这个也太小 2.若是因为前面的情况已经搜过,那我选择前面的就成了一个已经搜索过的情况) 2. 如果当前需要枚举的木板与上一块木板的大小相同,只选其中最后的那块,理由同上。 3. 如果剩下的木板大小比第一块还小,那么就是属于余料,将所有余料和已经切好的木料减去,剩下的木板长度如果比未切好的 x个木料总长还要小,那么这种状态也是不可行的 */#include#include #include using namespace std;inline int in(){ int x=0;char ch=getchar(); while(ch>'9' || ch<'0') ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}const int maxn=52;const int maxm=1025;const int INF=0x7f7f7f7f;int n,m,S,ans;int tmp[maxn];int a[maxn],b[maxm],s[maxm];bool cmp(const int &a,const int &b){ return a>b;}bool dfs(int x,int last){ if(!x) return true; if(S =b[x]){ a[i]-=b[x]; if(a[i] =b[i] && Minn>tmp[j]) Minn=tmp[j],Minx=j; if(Minx<0) return false; tmp[Minx]-=b[i]; } return true;}int main(){ n=in(); for(int i=1;i<=n;i++) a[i]=in(),S+=a[i]; m=in(); for(int i=1;i<=m;i++) b[i]=in(); sort(a+1,a+n+1); sort(b+1,b+m+1); for(int i=1;i<=m;i++) s[i]=s[i-1]+b[i]; int l=0,r=m,mid; if(check(r)){ printf("%d",m);return 0; } while(l+1>1; if(check(mid)) l=mid; else r=mid; } ans=r; while(dfs(ans,1) && ans<=m) ans++; printf("%d",ans-1); return 0;}