现在的位置: 首页 > 综合 > 正文

hdu 1059 多重背包

2013年07月07日 ⁄ 综合 ⁄ 共 985字 ⁄ 字号 评论关闭

题意:输入n1~n6 代表1~6的 个数,然后求这些数能不能通过分配达到value相等的状态

思路:多重背包(详见背包九讲) 能不能装满背包v/2的问题 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dp[100000];
int v;
bool flag;
void _com(int c , int w) {
    for(int i = 0 ; i <= v ; i ++) {
        if(i - c >= 0) 
        dp[i] = max(dp[i] , dp[i - c] + w);
        if(dp[v] == v) {
            flag = true;
            return;    
        }    
    }    
}
void _01(int c , int w) {
    for(int i = v ; i >= 0 ; i --) {
        if(i - c >= 0)
        dp[i] = max(dp[i] , dp[i - c] + w);
        if(dp[v] == v) {
            flag = true;
            return;    
        }    
    }    
}
void _mul(int c , int w , int cnt) {
    if(c*cnt>=v) {   //如果满足条件就完全背包 
        _com(c , w);
        return;        
    }  
    int k = 1;
    while(k < cnt) { //否则就二进制优化  
        _01(k*c , k*w);
        cnt -= k; 
        k = 2*k;   
    }
    _01(cnt*c , cnt*w);
}
int main() {
    int n[7];   
    int cas = 1; 
    while(cin>>n[1]>>n[2]>>n[3]>>n[4]>>n[5]>>n[6]) {
        if(!n[1] && !n[2] && !n[3] && !n[4] && !n[5] && !n[6]) break;
        flag = false;
        v = 0;
        for(int i = 1 ; i <= 6 ; i ++) {
            v += i*n[i];    
        }
        if(v%2==1) {      //偶数肯定不行 
            printf("Collection #%d:\n",cas++);
            printf("Can't be divided.\n\n");
            continue;        
        }
        v /= 2;
        memset(dp , 0 , sizeof(dp));
        for(int i = 1 ; i <= 6 ; i ++) {
            _mul(i , i , n[i]);
            if(flag) break;    
        }
        printf("Collection #%d:\n",cas++);
        if(flag) printf("Can be divided.\n\n");
        else printf("Can't be divided.\n\n");
    }
}

抱歉!评论已关闭.