I love sneakers!(最少分配一个问题)

题目链接

I love sneakers!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4246    Accepted Submission(s): 1732


Problem Description
After months of hard working, Iserlohn finally wins awesome amount of scholarship. As a great zealot of sneakers, he decides to spend all his money on them in a sneaker store.

There are several brands of sneakers that Iserlohn wants to collect, such as Air Jordan and Nike Pro. And each brand has released various products. For the reason that Iserlohn is definitely a sneaker-mania, he desires to buy at least one product for each brand.
Although the fixed price of each product has been labeled, Iserlohn sets values for each of them based on his own tendency. With handsome but limited money, he wants to maximize the total value of the shoes he is going to buy. Obviously, as a collector, he won’t buy the same product twice.
Now, Iserlohn needs you to help him find the best solution of his problem, which means to maximize the total value of the products he can buy.
 

Input
Input contains multiple test cases. Each test case begins with three integers 1<=N<=100 representing the total number of products, 1 <= M<= 10000 the money Iserlohn gets, and 1<=K<=10 representing the sneaker brands. The following N lines each represents a product with three positive integers 1<=a<=k, b and c, 0<=b,c<100000, meaning the brand’s number it belongs, the labeled price, and the value of this product. Process to End Of File.
 

Output
For each test case, print an integer which is the maximum total value of the sneakers that Iserlohn purchases. Print "Impossible" if Iserlohn's demands can’t be satisfied.
 

Sample Input
  
  
5 10000 3 1 4 6 2 5 7 3 4 99 1 55 77 2 44 66
 

Sample Output
  
  
255
 说实在的这道题目大家可以大概理解为是否存在某种状态问题
//这道题目说句实话,我还没与想明白,当然是一维的方法还没有想明白。
//二维的就在这里给大家说一下:
/*
if(dp[i][kk-G[i][j].pr]!=-1)
dp[i][kk]=max(dp[i][kk],dp[i][kk-G[i][j].pr]+G[i][j].v);
if(dp[i-1][kk-G[i][j].pr]!=-1){
dp[i][kk]=max(dp[i][kk],dp[i-1][kk-G[i][j].pr]+G[i][j].v);
********* 这个代码块很重要*******
1.if(dp[i][kk-G[i][j].pr]!=-1)
dp[i][kk]=max(dp[i][kk],dp[i][kk-G[i][j].pr]+G[i][j].v);
这个代码表示当我选择了眼前的这个物品的时候,判断我这个品牌是否已经选过一次了,如果选过,我可以接着选择;

**************************************************************************************8
【for(int kk=m; kk>=G[i][j].pr; kk--)】这个代码大家应该以前经常见到过便是那01背包的模板代码中的一部分。
至于为什么放在这里,为了说明上面以及下面那个代码块的又来。为什么要如此的判断。
众所皆知,大家都明白,按照这种循环方式,可以防止前一次的操作在这一次产生不应该产生的影响,
知道的明白,当他首次进入另一个品牌的选择时,每一个dp里面都是-1,如果,在这之前存在着的不是-1,那么证明,已经选择了一个当前品牌的产品。
然后再已经选了的基础上,我在选一个。
如此下面那个代码块也是这么理解。
便是不管这个产品选没有选,我都在上一个品牌选了的基础上选这个品牌中的一个产品,代表着,此时我只选了当前这个品牌的一个。
**************************************************************************************
2. if(dp[i-1][kk-G[i][j].pr]!=-1){
dp[i][kk]=max(dp[i][kk],dp[i-1][kk-G[i][j].pr]+G[i][j].v);
这个代码表示当我选择眼前的这个物品的时候,判断我的前面哪一个品牌是否选择了如果选择了,则可以选择了,如果没有选择证明,我的前一个品牌没有选到,
导致结果会是-1表示不满足条件
*/
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k;
struct po {
    int v,pr;
} pos;
int id;
vector<po>G[15];
void init(int mm) {
    for(int i=1; i<=mm; i++) {
        G[i].clear();
    }
}
int dp[15][10000+5];
int main() {
    while(~scanf("%d%d%d",&n,&m,&k)) {
        init(k);
        memset(dp,-1,sizeof(dp));
        for(int i=0; i<n; i++) {
            scanf("%d%d%d",&id,&pos.pr,&pos.v);
            G[id].push_back(pos);
        }
        for(int i=0; i<=10000; i++) {
            dp[0][i]=0;
        }
        for(int i=1; i<=k; i++) {
            for(int j=0; j<G[i].size(); j++) {
                for(int kk=m; kk>=G[i][j].pr; kk--) {
                    if(dp[i][kk-G[i][j].pr]!=-1)
                        dp[i][kk]=max(dp[i][kk],dp[i][kk-G[i][j].pr]+G[i][j].v);
                    if(dp[i-1][kk-G[i][j].pr]!=-1) {
                        dp[i][kk]=max(dp[i][kk],dp[i-1][kk-G[i][j].pr]+G[i][j].v);
                    }
                }
            }
        }
        if(dp[k][m]<0) {
            printf("Impossible\n");
        } else {
            printf("%d\n",dp[k][m]);
        }
    }
    return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值