码迷,mamicode.com
首页 > 其他好文 > 详细

hdu(1059) Dividing(多重背包)

时间:2015-02-05 23:11:56      阅读:200      评论:0      收藏:0      [点我收藏+]

标签:

题意:输入六个数,价值分别为1——6,输入的数代表该价值的物品的个数;求能否平均分。

key:如果奇数肯定不能分,直接输出答案。偶数的话,就是多重背包问题。 试过两种做法,第一种是背包九讲的二进制优化,写三个函数,分别是bag01, bagall, bagmulti~第二种是直接多重背包,但很可能tle,这题我交的就是tle了~

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
const int maxn = 120000 + 6;   //20000 * 6
int dp[maxn];
int val[8];  //输入的六组数
int sum, sumh;

using namespace std;

void bag01(int w, int v)          //01背包
{
    for(int i = sumh; i >= w; i--)
        if(dp[i] < dp[i - w] + v)
            dp[i] = dp[i - w] + v;
}

void allbag(int w, int v)   //完全背包
{
    for(int i = w; i <= sumh; i++)
        if(dp[i] < dp[i - w] + v)
            dp[i] = dp[i - w] + v;
}

void multibag(int w, int v, int n)   //多重背包,“背包九讲”有模版
{
    if(w * n >= sumh)           //假如重量 * 数量,大于背包,就变成完全背包的情况,即该物品可任意取
        allbag(w, v);
    else{                           //进行二进制优化
        int k = 1;
        while(k < n){
            bag01(k * w, k * v);
            n = n - k;
            k = 2 * k;
        }
            bag01(w * n, v * n);
    }
}


int main()
{
    int t = 1;
    while(scanf("%d%d%d%d%d%d", &val[1], &val[2], &val[3], &val[4], &val[5], &val[6]) != EOF){
        memset(dp, 0, sizeof(dp));
        sum = val[1] + val[2] * 2 + val[3] * 3 + val[4] * 4 + val[5] * 5 + val[6] * 6;
        if(sum == 0)
            break;
        sumh = sum / 2;
        if(sum % 2 != 0){          //奇数的话可直接输出不能
            printf("Collection #%d:\n", t);
            printf("Can‘t be divided.\n\n");
            t++;
            continue;
        }
        else{
            for(int i = 1; i <= 6; i++){            //多重背包
                multibag(i, i, val[i]);
            }
            if(dp[sumh] == sumh){
                printf("Collection #%d:\n", t);
                printf("Can be divided.\n\n");
                t++;
            }
            else{
                printf("Collection #%d:\n", t);
                printf("Can‘t be divided.\n\n");
                t++;
            }
        }
    }
    return 0;
}

下面的是TLE的,还要研究下怎样的数据范围才不会tle,这个代码简略点~

#include <iostream>
#include <stdio.h>

const int maxn = 120000 + 6;   //20000 * 6
int dp[maxn];
int val[8];  //输入的六组数
int sum, sumh;

using namespace std;

int main()
{
    int t = 1;
    while(scanf("%d%d%d%d%d%d", &val[1], &val[2], &val[3], &val[4], &val[5], &val[6]) != EOF){
        memset(dp, 0, sizeof(dp));
        sum = val[1] + val[2] * 2 + val[3] * 3 + val[4] * 4 + val[5] * 5 + val[6] * 6;
        if(sum == 0)
            break;
        sumh = sum / 2;
        if(sum % 2 != 0){          //奇数的话可直接输出不能
            printf("Collection #%d:\n", t);
            printf("Can‘t be divided.\n\n");
            t++;
            continue;
        }
        else{
            for(int i = 1; i <= 6; i++){  //多重背包
                int cnt[8];
                memset(cnt, 0, sizeof(cnt));
               for(int j = i;j <= sumh; j++){
                    if(cnt[j - i] + 1 <= val[i] && i + dp[j - i] > dp[j]){
                        dp[j] = i + dp[j - i];
                        cnt[j] = cnt[j - i];
                    }
               }
            }
            if(dp[sumh] == sumh){
                printf("Collection #%d:\n", t);
                printf("Can be divided.\n\n");
                t++;
            }
            else{
                printf("Collection #%d:\n", t);
                printf("Can‘t be divided.\n\n");
                t++;
            }
        }
    }
    return 0;
}

 

hdu(1059) Dividing(多重背包)

标签:

原文地址:http://www.cnblogs.com/Joe962850924/p/4276088.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!