【BZOJ1082】[SCOI2005]柵欄(搜索)
阿新 • • 發佈:2018-10-03
space include algorithm names std return [1] spa print
【BZOJ1082】[SCOI2005]柵欄(搜索)
題面
BZOJ
洛谷
題解
隨便寫個爆搜,洛谷上就\(80\)分了。先放爆搜代碼:
#include<iostream> #include<cstdio> using namespace std; inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n,m,a[55],b[1010],l[55],ans; void dfs(int x,int s) { if(s+n-x+1<=ans)return; if(x==n+1){ans=s;return;} dfs(x+1,s); for(int i=1;i<=m;++i) if(l[i]+b[x]<=a[i]) l[i]+=b[x],dfs(x+1,s+1),l[i]-=b[x]; } int main() { m=read(); for(int i=1;i<=m;++i)a[i]=read(); n=read(); for(int i=1;i<=n;++i)b[i]=read(); dfs(1,0); printf("%d\n",ans); }
然後發現可以二分,二分之後再玄學剪枝就好了。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n,m,a[55],b[1010],sum,tot,s[1010]; bool dfs(int x,int lst) { if(!x)return true; if(sum+s[x]>tot)return false; for(int i=lst;i<=m;++i) if(b[x]<=a[i]) { a[i]-=b[x];if(a[i]<b[1])sum+=a[i]; bool fl=dfs(x-1,b[x]==b[x-1]?i:1); if(a[i]<b[1])sum-=a[i];a[i]+=b[x]; if(fl)return true; } return false; } int main() { m=read();for(int i=1;i<=m;++i)tot+=(a[i]=read()); n=read();for(int i=1;i<=n;++i)b[i]=read(); sort(&a[1],&a[m+1]);sort(&b[1],&b[n+1]); for(int i=1;i<=n;++i)s[i]=s[i-1]+b[i]; while(s[n]>tot)--n; int l=0,r=n,ret=0; while(l<=r) { int mid=(l+r)>>1; if(dfs(mid,1))l=mid+1,ret=mid; else r=mid-1; } printf("%d\n",ret);return 0; }
【BZOJ1082】[SCOI2005]柵欄(搜索)