poj 2923 Relocation (枚舉+背包 | 狀態壓縮+01背包)

來源:互聯網
上載者:User

連結:

http://poj.org/problem?id=2923

題目大意:

有N件傢具,每件的重量為(1 ≤ wi ≤ 100), 用兩輛車把他們來運送到目的地。這兩輛車的限載重量分別為C1, C2(1 ≤ Ci ≤ 100) , 問最少幾趟可以把所有傢具運送到目的地。

這兩輛車每趟都必須一起走,即使某輛車沒載東西。

思路:

(一)

先上自己的方法:

枚舉第一輛車可能載的傢具的所有組合情況,那麼用二進位來表示狀態則共有 1<<n ,如果二進位的第i位上是1,那麼就表示第i件傢具是由第一輛車運的。

這樣就相當於把所有傢具分成了兩組,一組給第一輛車運,另一組給第二輛車運。

然後分別對這兩組資料計算,分別最少幾次可以運完,這樣,問題就轉換為了:給n個傢具,和一輛限載重量c的車,這輛車最少幾次可以運完。

由貪心的思想可以知道,每次運送應該儘可能的裝滿這輛車,那麼用01背包,背包容量為限載重量c,每個傢具的重量即是價值也是耗費, f[c]就是這次運送的。選擇完一次後,把那些選擇過的傢具刪除掉,繼續再做01背包選擇,直到所有傢具全部選擇完。至於記錄選擇了哪些傢具,方法和記錄路徑一樣。

然後,這兩輛車分別運送次數取較大的,就是這個枚舉到的這個方案的最少次數。

(二)

這個方法是學習的,網上的基本都是這個方法,不再細講。

大概思路是,用二進位表示選擇狀態,先預先處理所有選擇的組合,看這個組選擇的傢具能否被兩輛車子一次運過去,如果可以的話就“打包”起來看作是一個物體,然後再對所有物體進行01背包。

 

代碼:

方法一:

#include<iostream>#include<queue>#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<vector>#include<string>#define MP make_pair#define SQ(x) ((x)*(x))const double PI = acos(-1.0);const int INF = 0x3f3f3f3f;using namespace std;typedef long long int64;const int MAXN = 12;int n, m;int c1, c2;int f[110];int w[MAXN];int ans;bool path[MAXN][110];vector<int>w1, w2;bool check(int x){    for(int i=0; i<n; ++i){        if((x>>i)&1){            if(w[i]>c1) return false;        }else{            if(w[i]>c2) return false;        }    }     return true;}void init(int x){    w1.clear(); w2.clear();    for(int i=0; i<n; ++i){        if((x>>i)&1){            w1.push_back(w[i]);        }else            w2.push_back(w[i]);    }}void update(vector<int>&w, int i, int j){    if(i<0) return ;    int tmp = w[i];    if(path[i][j]){        w.erase(w.begin()+i);        update(w, i-1, j-tmp);    }else        update(w, i-1, j);}int counter(vector<int>& w, int c){    if(w.size()==0)  return 0;       int cnt = 0;    do{        cnt++;        if(cnt >= ans) return cnt;        memset(f, 0, sizeof(f));        memset(path, 0, sizeof(path));                for(int i=0; i<w.size(); ++i){            for(int v=c; v>=w[i]; --v){                if(f[v-w[i]]+w[i] >= f[v]){                    f[v] = f[v-w[i]]+w[i];                    path[i][v] = 1;                }            }        }        update(w, w.size()-1, c);    }while(w.size());    return cnt;}int main(){    int nCase, cas=1, x;    scanf("%d", &nCase);    while(nCase--){        printf("Scenario #%d:\n", cas++);        scanf("%d%d%d", &n,&c1,&c2);        for(int i=0; i<n; ++i)            scanf("%d", &w[i]);        ans = INF;        int sta = 0;        while(sta < (1<<n)){            if(!check(sta)){                sta++;                continue;             }            init(sta);            int cnt1 = counter(w1, c1);            int cnt2 = counter(w2, c2);            ans = min(ans, max(cnt1, cnt2));            sta++;        }        printf("%d\n\n", ans);    }    return 0;} 

方法二:

#include<iostream>#include<queue>#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<vector>#include<string>#define MP make_pair#define SQ(x) ((x)*(x))const double PI = acos(-1.0);const int INF = 0x3f3f3f3f;using namespace std;typedef long long int64;const int MAXN = 15;int n, m;int c1, c2;int w[MAXN], d[2000];int sta[2000], idx;bool check(int x){    int sum = 0 ;    for(int i=0; i<=c1; ++i) d[i] = 0;    d[0] = 1;    for(int i=0; i<n; ++i) if((x>>i)&1){         sum += w[i];        for(int v=c1; v>=w[i]; --v)            d[v] = max(d[v], d[v-w[i]]+w[i]);    }    if(sum > c1+c2) return false;    return sum-d[c1] <= c2;}int main(){    int nCase, cas=1, x;    scanf("%d", &nCase);    while(nCase--){        printf("Scenario #%d:\n", cas++);        scanf("%d%d%d", &n,&c1,&c2);        for(int i=0; i<n; ++i)            scanf("%d", &w[i]);        idx = 0;        int i = 1;        while(i < (1<<n)){            if(check(i)){                sta[idx++] = i;            }            ++i;        }        for(int i=0; i<(1<<n); ++i) d[i]=INF;        d[0] = 0;        for(int i=0; i<idx; ++i){            for(int j=((1<<n)-1); j>=0; --j){                if(d[j] == INF) continue;                if((j&sta[i]) == 0){                    d[j|sta[i]] = min(d[j|sta[i]], d[j]+1);                }            }        }        printf("%d\n\n", d[(1<<n)-1]);    }    return 0;} 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.