BZOJ1082: [SCOI2005]栅栏
1082: [SCOI2005]柵欄
Time Limit:?10 Sec??Memory Limit:?162 MBSubmit:?1906??Solved:?816
[Submit][Status][Discuss]
Description
農夫約翰打算建立一個柵欄將他的牧場給圍起來,因此他需要一些特定規格的木材。于是農夫約翰到木材店購
買木材。可是木材店老板說他這里只剩下少部分大規格的木板了。不過約翰可以購買這些木板,然后切割成他所需
要的規格。而且約翰有一把神奇的鋸子,用它來鋸木板,不會產生任何損失,也就是說長度為10的木板可以切成長
度為8和2的兩個木板。你的任務:給你約翰所需要的木板的規格,還有木材店老板能夠給出的木材的規格,求約翰
最多能夠得到多少他所需要的木板。
Input
第一行為整數m(m<= 50)表示木材店老板可以提供多少塊木材給約翰。緊跟著m行為老板提供的每一塊木板的長
度。接下來一行(即第m+2行)為整數n(n <= 1000),表示約翰需要多少木材。接下來n行表示他所需要的每一塊木板
的長度。木材的規格小于32767。(對于店老板提供的和約翰需要的每塊木板,你只能使用一次)。
Output
只有一行,為約翰最多能夠得到的符合條件的木板的個數。
Sample Input
430
40
50
25
10
15
16
17
18
19
20
21
25
24
30
Sample Output
7HINT
?
25切出 21 30切出 20 40切出 19、18 50切出 15、16、17
?
Source
題解:神奇的DFS+剪枝
二分答案:我們先排序所有需要裁出來的木頭,再二分答案!
DFS:我們考慮每塊木頭由誰裁剪出來 時間復雜度:n^m
剪枝:1.當出現答案時,不再回溯!
2.當剩下的木材<需要裁的木材時!
3.當當前木材大小等于前一個木材大小時,從它的最小匹配開始!【這個剪枝是最關鍵的】
總結:反正這樣就A了,而且跑的飛快,我一直認為剪枝這種東西過于玄幻,
導致我這種弱菜根本不會分析時間復雜度,果然暴力出奇跡這句話是沒錯的!
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #define ll long long #define ld long double #define N 1005 using namespace std; int n,m,sa,mid,ans; int a[N],b[N],sb[N],bl[N]; bool bool_flag; int read() {int x=0,f=1; char ch;while (ch=getchar(),ch<'0'||ch>'9') if (ch=='-') f=-1;while (x=x*10+ch-'0',ch=getchar(),ch>='0'&&ch<='9');return x*f; } void dfs(int A,int B,int w) {if (B==0) {bool_flag=1; return;}while (A<=n && a[A]<b[1]) w+=a[A],A++;if (bool_flag || w+sb[mid]>sa || A>n) return;int t=A,t1=A,t2=B,t3=w;if (b[B]==b[B+1] && B!=mid) t=bl[B+1];for (int i=t; i<=n; i++){if (a[i]>=b[B]){bl[B]=i; a[i]-=b[B]; B--; dfs(A,B,w);A=t1; B=t2; w=t3; a[i]+=b[B]; }} } int main() {n=read(); for (int i=1; i<=n; i++) a[i]=read();m=read(); for (int i=1; i<=m; i++) b[i]=read();sort(a+1,a+n+1); sort(b+1,b+m+1);while (b[m]>a[n]) m--; int tot=0;for (int i=1; i<=n; i++) if (a[i]>b[1]) a[++tot]=a[i];n=tot;for (int i=1; i<=n; i++) sa+=a[i];sb[0]=0; for (int i=1; i<=m; i++) sb[i]=sb[i-1]+b[i];int l=1,r=m; // cout<<" "<<n<<" "<<m<<endl;while (l<=r){mid=(l+r)>>1; bool_flag=0; dfs(1,mid,0);if (bool_flag) ans=mid,l=mid+1; else r=mid-1;}printf("%d\n",ans);return 0; } /* 4 30 40 50 25 10 20 20 20 20 20 20 20 20 20 20*/?
轉載于:https://www.cnblogs.com/HQHQ/p/6036458.html
總結
以上是生活随笔為你收集整理的BZOJ1082: [SCOI2005]栅栏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最完美的xslt数值函数与字符串函数(转
- 下一篇: iOS -数据库网络之xml解析之远程解