1. 程式人生 > 實用技巧 >【多重揹包】B001_AW_劃分大理石(二進位制優化 / 貪心+dp)

【多重揹包】B001_AW_劃分大理石(二進位制優化 / 貪心+dp)

有價值分別為1..6的大理石各a[1..6]塊,現要將它們分成兩部分,使得兩部分價值之和相等,問是否可以實現。

其中大理石的總數不超過20000。

輸入格式
輸入包含多組資料!
每組資料佔一行,包含6個整數,表示a[1]~a[6]。
當輸入為0 0 0 0 0 0時表示輸入結束,且該行無需考慮。
輸出格式
每組資料輸出一個結果,每個結果佔一行。
如果可以實現則輸出“Can”,否則輸出“Can’t”

輸入樣例:
4 7 4 5 9 1
9 8 1 7 2 4
6 6 8 5 9 2
1 6 6 1 0 7
5 9 3 8 8 4
0 0 0 0 0 0
輸出樣例:
Can't
Can
Can't
Can't
Can

方法一:二進位制優化 dp

T...

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int n=6, m=120005;
int k=1, w[n+1], f[m];

int main() {
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    while (true) {
        ll x,s=0;
        for (int i=1; i<=n; i++) {
            cin>>x, s+=i*x;
            for (int j=1; j<=x; j<<=1) w[k++]=i*j, x-=j;
            if (x) w[k++]=i*x;
        }
        if (s==0) break;
        if (s&1) cout << "Can't\n";
        else {
            f[0]=1;
            for (int i=1; i<=k; i++)     
            for (int j=m; j>=w[i]; j--) {
                f[j]|=f[j-w[i]];
            }
            cout << (f[s/2] ? "Can\n" : "Can't\n");
        }
    }    
    return 0;
}

複雜度分析

  • Time\(O(nlog_2x)\)
  • Space\(O(...)\)

方法二:貪心+dp


複雜度分析

  • Time\(O()\)
  • Space\(O()\)