codevs 2456柵欄
阿新 • • 發佈:2017-06-17
class ostream 跟著 middle har cti script %d b-s
輸入描述 Input Description
傳送門
2456 柵欄
2006年省隊選拔賽四川
時間限制: 1 s 空間限制: 128000 KB 題目等級 : 大師 Maste 題目描述 Description農夫約翰打算建立一個柵欄將他的牧場給圍起來,因此他需要一些特定規格的木材。於是農夫約翰到木材店購買木材。可是木材店老板說他這裏只剩下少部分大規格的木板了。不過約翰可以購買這些木板,然後切割成他所需要的規格。而且約翰有一把神奇的鋸子,用它來鋸木板,不會產生任何損失,也就是說長度為10的木板可以切成長度為8和2的兩個木板。
你的任務:給你約翰所需要的木板的規格,還有木材店老板能夠給出的木材的規格,求約翰最多能夠得到多少他所需要的木板。
第一行為整數m(m<= 50)表示木材店老板可以提供多少塊木材給約翰。緊跟著m行為老板提供的每一塊木板的長度。接下來一行(即第m+2行)為整數n(n <= 1000),表示約翰需要多少木材。接下來n行表示他所需要的每一塊木板的長度。木材的規格小於32767。(對於店老板提供的和約翰需要的每塊木板,你只能使用一次)。
輸出描述 Output Description只有一行,為約翰最多能夠得到的符合條件的木板的個數。
樣例輸入 Sample Input4
30
40
50
25
10
15
16
17
18
19
20
21
25
24
30
樣例輸出 Sample Output7
數據範圍及提示 Data Size & Hint見題面
【題目大意】
給你幾塊一定長度而木材,問最多能切多少塊需要長度的木塊。
【思路1】
哈哈哈30分暴力 好高興哦\\QWq//
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int m,n,l[55],ned[1002],vis[55],ans,res=-0x7ffff; void dfs(int x) { if(x==n+1) { res=max(res,ans); return ; } for(int i=1; i<=m; i++) { if(l[i]>ned[x]) { l[i]-=ned[x]; ans++; dfs(x+1); l[i]+=ned[x]; ans--; } } dfs(x+1); } int main() { scanf("%d",&m); for(int i=1; i<=m; i++) scanf("%d",&l[i]); scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&ned[i]); sort(l+1,l+m+1); sort(ned+1,ned+n+1); dfs(1); printf("%d\n",res); return 0; }
【思路2--正解】
二分搜索+剪枝
我真沒看出來這個題是二分......
二分剪mid塊。剪最小的mid塊....
說一下剪枝
(1) 如果浪費的木材+我們二分需要的木材大於商店給出的木材和false。
(2)如果需要的木材有兩塊相同的話,再dfs時不需要從1開始找切哪塊木材,從上一次for循環開始搜。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,m,ned[1005],nes[1002],l[1002]; int sum,ans,was; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } bool dfs(int get,int from) { if(!get)return true; if(was+nes[get]>sum)return false; bool can=0; for(int i=from; i<=m; i++) { if(l[i]>=ned[get]) { l[i]-=ned[get]; if(l[i]<ned[1])was+=l[i]; if(ned[get]==ned[get-1]) can=dfs(get-1,i); else can=dfs(get-1,1); if(l[i]<ned[1]) was-=l[i]; l[i]+=ned[get]; if(can)return true; } } return false; } int main() { m=read(); for(int i=1; i<=m; i++) { l[i]=read(); sum+=l[i]; } n=read(); for(int i=1; i<=n; i++) ned[i]=read(); sort(l+1,l+m+1); sort(ned+1,ned+n+1); for(int i=1; i<=n; i++) nes[i]=nes[i-1]+ned[i]; for(; nes[n]>sum;)n--; int lt=1,rt=n; while(lt<=rt) { // was=0; int mid=lt+(rt-lt)/2; if(dfs(mid,1))ans=mid,lt=mid+1; else rt=mid-1; } printf("%d\n",ans); return 0; }
codevs 2456柵欄