hdu 3033 I love sneakers!

本来想着早起一水的。。。结果拖到现在才解决。。。题意是有k种鞋子, 每种鞋子有num种,每种都有其价格和value。要求给定m块钱,每种鞋子至少买一种,求最大的value值,不能满足则输出“Impossible”。

算是背包变形吧。想了很久,觉得就要接近正确思想了,但是每种鞋子至少买一种那部分不知道怎么搞,刚开始写了个枚举每一种鞋子第i种必买,然后对剩下的做01背包的程序,无奈sample都过不了。。。弱爆了。。。

于是猫了一眼网上的题解,由于这题自己思考了很久了,一看题解便顿悟了。。用结构体二位数组g[i][j]保存第i种鞋子的第j种型号的信息。dp[i][j]表示购买前i种鞋子,花费j块钱得到得最大value值,那么对于g[i][j]鞋子,有两种状态,要么从上组中继承过来,要么从这一组的前面继承过来,前提是上一种状态可到达(解决每种至少买一个)。状态转移是不难的。。。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn =  100001;
struct SHOES
{
    int v, w;
}g[11][111];
int n, m, k, num[11], dp[11][maxn];

int main()
{
    while(~scanf("%d%d%d", &n, &m, &k))
    {
        memset(dp, -1, sizeof(dp));
        memset(dp[0], 0, sizeof(dp[0]));
        memset(num, 0, sizeof(num));
        
        int a, b, c;
        for(int i=0; i<n; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            g[a][num[a]].v = b;
            g[a][num[a]++].w = c;
        }
        
        for(int i=1; i<=k; i++)
        {
            for(int j=0; j<num[i]; j++)
            {
                for(int V=m; V>=g[i][j].v; V--)
                {
                    if(dp[i][V-g[i][j].v] != -1) //从第i种鞋子前面继承并且可到达
                        dp[i][V] = max(dp[i][V], dp[i][V-g[i][j].v] + g[i][j].w);
                    if(dp[i-1][V-g[i][j].v] != -1)  //从第i-1种鞋子继承并且可到达
                        dp[i][V] = max(dp[i][V], dp[i-1][V-g[i][j].v] + g[i][j].w);
                }
            }
        }
        if(dp[k][m] < 0)    puts("Impossible");
        else    printf("%d\n", dp[k][m]);
    }
}


你可能感兴趣的:(hdu 3033 I love sneakers!)