POJ 1170 Shopping Offers 6进制压缩状态+完全背包

题意:有n(n<=5)种物品,每种个数num<=5,价值1<=val<=999,现在商店推出m(m<=99)种促销方案,即若干种物品放在一起价格会比单个物品的总和便宜,
          问买到所有物品的最少花多少钱。

题解:因为n和num很小,所以想到n维dp,但是不好处理,想到用6进制6位表示状态,然后对每种促销方案做完全背包就好了。

Sure原创,转载请注明出处。

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <map>
using namespace std;
const int inf = 1 << 29;
const int maxn = 8;
const int maxm = 8000;
const int val[maxn] = {1,6,36,216,1296,7776};
struct cargo
{
    int num,val;
}bag[maxn];
int dp[maxm],st[maxn],cur[maxn];
map <int , int> hash;
int m,n,tot;

inline int MIN(int a,int b)
{
    return a < b ? a : b;
}

inline void in(int &a)
{
    char ch;
    while(ch = getchar(), ch < '0' || ch > '9');
    a = ch - '0';
    while(ch = getchar(), ch >= '0' && ch <= '9')
    {
        a = a * 10 + ch - '0';
    }
    return;
}

int load(int s[])
{
    int ans = 0;
    for(int i=1;i<=n;i++)
    {
        ans += val[i-1] * s[i];
    }
    return ans;
}

void upload(int x,int s[])
{
    for(int i=1;i<=n;i++)
    {
        s[i] = x % 6;
        x /= 6;
    }
    return;
}

void read()
{
    hash.clear();
    int x;
    for(int i=1;i<=n;i++)
    {
        in(x),in(bag[i].num),in(bag[i].val);
        hash[x] = i;
        st[i] = bag[i].num;
    }
    tot = load(st);
    return;
}

void init()
{
    for(int i=0;i<=tot;i++)
    {
        int res = 0;
        upload(i , st);
        for(int j=1;j<=n;j++)
        {
            if(st[j] > bag[j].num)
            {
                res = inf;
                break;
            }
            else
            {
                res += bag[j].val * st[j];
            }
        }
        dp[i] = res;
    }
    return;
}

void update(int val)
{
    for(int i=0;i<=tot;i++)
    {
        upload(i , st);
        bool flag = true;
        for(int j=1;j<=n;j++)
        {
            st[j] += cur[j];
            if(st[j] > bag[j].num)
            {
                flag = false;
                break;
            }
        }
        if(flag)
        {
            int nxt = load(st);
            dp[nxt] = MIN(dp[nxt] , dp[i] + val);
        }
    }
    return;
}

void solve()
{
    in(m);
    int num,x,c,p;
    while(m--)
    {
        memset(cur,0,sizeof(cur));
        in(num);
        for(int i=0;i<num;i++)
        {
            in(x),in(c);
            x = hash[x];
            cur[x] = c;
        }
        in(p);
        update(p);
    }
    printf("%d\n",dp[tot]);
    return;
}

int main()
{
    while(~scanf("%d",&n))
    {
        read();
        init();
        solve();
    }
    return 0;
}


你可能感兴趣的:(c,struct,upload)