HD 48DP 1171 多重背包问题

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1171
以前做多重背包的问题。都是直接用母函数做的。但是这次不能了- -,因为这个数据有点多。。用母函数肯定要跑很久。要是和上次那个6个数字一样用母函数就好很多了。多重背包问题其实最主要的就是多一次预处理。因为二进制可以表示任意10进制的数。所以通过二进制的思路进行预处理。后来就当做普通的01背包问题就行了。

#include <bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 5005;

int p[_max],c[_max];
int np[_max]; 
int dp[250005];
int main(){
    IOS;
    int n,sum,sum1,cnt;
    while(cin>>n && n>0){
        memset(dp,0,sizeof(dp));
        memset(np,0,sizeof(np));
        sum = 0,cnt = 0,sum1 = 0;
        for(int i = 1 ; i <= n ; i++){
            cin>>p[i]>>c[i];
            sum1 += p[i]*c[i];
        }
        sum = sum1/2;
        for(int i = 1 ; i <= n ; i++){
            int t = 1;
            while(c[i] >= t){
                np[++cnt] = p[i]*t;
                c[i] -= t;
                t *= 2;
            }
            if(c[i]) np[++cnt] = p[i]*c[i];
        } //二进制优化 
        sort(np+1,np+cnt+1);
        for(int i = 1 ; i <= cnt ; i++){
            if(np[i] > sum) break;
            for(int j = sum ; j >= np[i] ; j--){
                dp[j] = max(dp[j],dp[j-np[i]]+np[i]);
            }
        }//背包 
        cout<<sum1-dp[sum]<<' '<<dp[sum]<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38987374/article/details/79799436
HD
今日推荐