1. 程式人生 > >【多重揹包+二進位制優化】ACM-ICPC 2018 焦作賽區網路預賽 - K. Transport Ship

【多重揹包+二進位制優化】ACM-ICPC 2018 焦作賽區網路預賽 - K. Transport Ship

題目連結<https://nanti.jisuanke.com/t/31720>


題意:

給出若干個船,每個船都有V[i]的容量,和2^{C[i]}的數量。有Q次詢問,給出一定體積的貨物,問你恰好裝滿的方案數量。


題解:

很明顯的多重揹包,但是要加上二進位制優化。

所謂二進位制優化就是把數量拆成2^0,2^1,2^2,2^3.....2^(k-1) , c-2^k+1,使得演算法複雜度降為log級別。

由於題目的數量是2的冪次,拆出來的數是沒有最後一項的。


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
const ll mod=1e9+7;
ll v[N],c[N],dp[N],n,m,x;
int main(){
    ll t;
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&m);
        memset(dp,0,sizeof(dp));
        for(ll i=1;i<=n;i++)
            scanf("%lld%lld",&v[i],&c[i]);
        dp[0]=1;
        for(ll i=1;i<=n;i++){
            ll tmp=1;
            for(ll j=0;j<c[i];j++){
                for(ll k=10000;k>=tmp*v[i];k--){
                    dp[k]=(dp[k]+dp[k-tmp*v[i]])%mod;
                }
                tmp<<=1;
            }
        }
        while(m--){
            scanf("%lld",&x);
            printf("%lld\n",dp[x]);
        }
    }
    return 0;
}