1. 程式人生 > >codevs 2456柵欄

codevs 2456柵欄

class ostream 跟著 middle har cti script %d b-s

傳送門

2456 柵欄

2006年省隊選拔賽四川

時間限制: 1 s 空間限制: 128000 KB 題目等級 : 大師 Maste 題目描述 Description

農夫約翰打算建立一個柵欄將他的牧場給圍起來,因此他需要一些特定規格的木材。於是農夫約翰到木材店購買木材。可是木材店老板說他這裏只剩下少部分大規格的木板了。不過約翰可以購買這些木板,然後切割成他所需要的規格。而且約翰有一把神奇的鋸子,用它來鋸木板,不會產生任何損失,也就是說長度為10的木板可以切成長度為8和2的兩個木板。

你的任務:給你約翰所需要的木板的規格,還有木材店老板能夠給出的木材的規格,求約翰最多能夠得到多少他所需要的木板。

輸入描述 Input Description

第一行為整數m(m<= 50)表示木材店老板可以提供多少塊木材給約翰。緊跟著m行為老板提供的每一塊木板的長度。接下來一行(即第m+2行)為整數n(n <= 1000),表示約翰需要多少木材。接下來n行表示他所需要的每一塊木板的長度。木材的規格小於32767。(對於店老板提供的和約翰需要的每塊木板,你只能使用一次)。

輸出描述 Output Description

只有一行,為約翰最多能夠得到的符合條件的木板的個數。

樣例輸入 Sample Input
4
30
40
50
25
10
15

16

17
18
19
20
21
25
24

30

樣例輸出 Sample Output

7

數據範圍及提示 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柵欄