CODEVS 3269 混合揹包

畫船聽雨發表於2014-11-16

一道裸的混合揹包題目,但是忘記了去重一直TLE,就是如果體積<=完全揹包的01,和多重揹包都要被完全揹包取代,因為他的數量沒限制所以用起來更方便。

題目連線:http://codevs.cn/problem/3269/

#include <iostream>
#include <string.h>
#include <cstdio>
#include <cstdlib>
using namespace std;

const int maxn = 210;
const int maxc = 200010;


inline int read()
{
    char ch;
    bool flag = false;
    int a = 0;
    while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-')));
    if(ch != '-')
    {
        a *= 10;
        a += ch - '0';
    }
    else
    {
        flag = true;
    }
    while(((ch = getchar()) >= '0') && (ch <= '9'))
    {
        a *= 10;
        a += ch - '0';
    }
    if(flag)
    {
        a = -a;
    }
    return a;
}
void write(int a)
{
    if(a < 0)
    {
        putchar('-');
        a = -a;
    }
    if(a >= 10)
    {
        write(a / 10);
    }
    putchar(a % 10 + '0');
}

int f[maxc], v[maxn], w[maxn], m[maxn];
int n, V;
bool vis[maxn];

void complete_pack(int cost, int weight)
{
    for(int j = cost; j <= V; j++)
        f[j] = max(f[j], f[j-cost]+weight);
}

void zero_pack(int cost, int weight)
{
    for(int j = V; j >= cost; j--)
        f[j] = max(f[j], f[j-cost]+weight);
}

void multi_pack(int cost, int weight, int amount)
{
    if(cost*amount >= V)
    {
        complete_pack(cost, weight);
        return;
    }
    int k = 1;
    while(k < amount)
    {
        zero_pack(cost*k, weight*k);
        amount -= k;
        k <<= 1;
    }
    zero_pack(amount*cost, amount*weight);
}
int main()
{
    n = read();
    V = read();
    memset(vis, false, sizeof(vis));
    for(int i=1; i<=n; i++)
    {
        v[i] = read();
        w[i] = read();
        m[i] = read();
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = i+1; j <= n; j++)
        {
            if(m[i] == 1)
            {
                if(m[j] == -1)if(v[i] >= v[j] && w[i] <= w[j]) vis[i] = true;
                if(m[j] > 1)if(v[i] >= v[j] && w[i] <= w[j]) vis[i] = true;
            }
            else if(m[i] > 1)
            {
                if(m[j] == -1)
                if(v[i] >= v[j] && w[i] <= w[j]) vis[i] = true;
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        if(m[i]==1 && !vis[i])
            zero_pack(v[i], w[i]);
        else if(m[i]==-1)
            complete_pack(v[i], w[i]);
        else if(!vis[i])multi_pack(v[i], w[i],m[i]);
    }
    write(f[V]);
    return 0;
}


相關文章