题意:

  有n<=100双鞋子,分别属于一个牌子,共k<=10个牌子。现有m<=10000钱,问每个牌子至少挑1双,能获得的最大价值是多少?

思路:

  分组背包的变形,变成了相反的,每组物品至少挑1件(分组背包问题是至多挑1件)。

  由于每个牌子至少买1双,那么可以先装一件最便宜的进去,如果有好的再更新(注意每次的容量下限)。而且同一双鞋子不能多次购买,这里要用01背包。对于当前容量cap,可能只装了某一牌子的一双鞋子(不一定最便宜),也可能装了多双,也可能只装了那双硬塞进去的最便宜的。

  注意点:有的店可是不一定有鞋子的;可能某个牌子连一双都买不起;可能买不全所有牌子。

  重写了次:

 //#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define back que[rear-1]
#define INF 0x3f3f3f3f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI = acos(-1.0);
const int N=;
int dp[][N];
struct node
{
int p,v;
}r;
vector<node> vect[N];
inline int cmp(node a,node b){return a.p<b.p;}
bool cal(int n,int m,int k)
{
for(int i=; i<=n; i++) //排序方便处理
sort(vect[i].begin(),vect[i].end(),cmp);
int sum=; //最便宜的鞋子价钱之和
for(int i=; i<=k; i++) //枚举组
{
if(vect[i].empty()) return false; //无鞋 node a=vect[i][];
for(int j=m; j-a.p>=sum; j--) //先装进去一个最便宜的
dp[i][j]=dp[i-][j-a.p]+a.v; for(int t=; t<vect[i].size(); t++) //考虑此组其他鞋
{
a=vect[i][t];
for(int j=m; j-a.p>=sum; j--)
{
dp[i][j]=max(dp[i][j], dp[i-][j-a.p]+a.v ); //注意点
dp[i][j]=max(dp[i][j], dp[i][j-a.p]+a.v );
}
}
sum+=vect[i][].p;
if(sum>m) return false; //买不起
}
return true;
} int main()
{
//freopen("input.txt", "r", stdin);
int w, n, m, k;
while(cin>>n>>m>>k) //n双鞋子,m钱,k个牌子
{
memset(dp,,sizeof(dp));
for(int i=; i<=k; i++) vect[i].clear();
for(int i=; i<=n; i++)
{
scanf("%d%d%d", &w, &r.p, &r.v);
vect[w].push_back(r); //分组保存
}
if(cal(n,m,k)) printf("%d\n",dp[k][m]);
else printf("Impossible\n");
}
return ;
}

AC代码

 #include <bits/stdc++.h>
using namespace std;
int n, m, k, w, dp[][];
struct node
{
int p,v;
}r;
vector< vector<node> > vect;
inline int cmp(node a,node b){return a.p< b.p? : ;}
int cal()
{
memset(dp,,sizeof(dp));
int up=;
for(int i=; i<=k; i++) //每组
{
r=vect[i][];
for(int j=m; j>=up+r.p; j--) //先装进去每组中最便宜的一个,有更好的再更新
dp[i][j]=dp[i-][j-r.p]+r.v; for(int t=; t<vect[i].size(); t++)//同组每种鞋
{
r=vect[i][t];
for(int j=m; j>=up+r.p; j--) //每种容量。注意下限是前面所有店的最便宜鞋价的总和。最差也能买上前面所有店的最便宜的鞋子,其他都是无效的状态。
{
dp[i][j]=max(dp[i][j], dp[i-][j-r.p]+r.v ); //单独放。
dp[i][j]=max(dp[i][j], dp[i][j-r.p] +r.v ); //配合同组放。
}
}
up+=vect[i][].p; //更新下限
}
if(dp[k][m]>) return ;
else return ;
}
void init()
{
vect.clear();
vector<node> tmp;
for(int i=; i<=k; i++) vect.push_back(tmp);
} int main()
{
freopen("input.txt", "r", stdin);
while(cin>>n>>m>>k)
{
init();
for(int i=; i<n; i++)
{
scanf("%d%d%d", &w, &r.p, &r.v);
vect[w].push_back(r);//分组保存
}
int big=;
for(int i=; i<=k; i++)
{
sort(vect[i].begin(), vect[i].end(), cmp); //排个序,最低价的排在前面
if(!vect[i].empty()) big+=vect[i][].p; //坑在这,有的店完全没有鞋子!
else big=0x7fffffff;//既然没有鞋子,置为无穷大,表示买不起。
}
if(big>m){printf("Impossible\n");continue;} //每家店最便宜的鞋子都买不起
if(cal()) printf("%d\n",dp[k][m]);
else printf("Impossible\n");
}
return ;
}

AC代码

HDU 3033 I love sneakers! 我爱运动鞋 (分组背包+01背包,变形)的更多相关文章

  1. hdu 3033 I love sneakers! 分组背包

    I love sneakers! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  2. [HDU 3033] I love sneakers! (动态规划分组背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3033 题意:给你K种品牌,每种品牌有不同种鞋,现在每种品牌至少挑一款鞋,问获得的最大价值,如果不能每种 ...

  3. hdu 3033 I love sneakers!

    I love sneakers! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  4. hdu 3033 I love sneakers!(分组背包+每组至少选一个)

    I love sneakers! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  5. hdu 2126 Buy the souvenirs 【输出方案数】【01背包】(经典)

    题目链接:https://vjudge.net/contest/103424#problem/K 转载于:https://blog.csdn.net/acm_davidcn/article/detai ...

  6. HDU 1011 Starship Troopers【树形DP/有依赖的01背包】

    You, the leader of Starship Troopers, are sent to destroy a base of the bugs. The base is built unde ...

  7. HDU - 5887 2016青岛网络赛 Herbs Gathering(形似01背包的搜索)

    Herbs Gathering 10.76% 1000ms 32768K   Collecting one's own plants for use as herbal medicines is pe ...

  8. HDU 3033 组合背包变形 I love sneakers!

    I love sneakers! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. hdu 3033(好题,分组背包)

    I love sneakers! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

随机推荐

  1. CS231n 2016 通关 第五、六章 Fully-Connected Neural Nets 作业

    要求:实现任意层数的NN. 每一层结构包含: 1.前向传播和反向传播函数:2.每一层计算的相关数值 cell 1 依旧是显示的初始设置 # As usual, a bit of setup impor ...

  2. OpenFileDialog无法弹出的解决方法

    今天在写一个socket通信的winform小程序,由于socket的receive方法会阻塞线程,所以就使用了多线程解决.但在新建的线程中创建OpenFileDialog并调用其ShowDialog ...

  3. Firebug的安装与使用

    第一步,点击 Firefox 浏览器上的“工具”选项,然后点击“附加软件”,在弹出的小窗口中,点击右下角的“获取扩展”选项,如图 4 所示. 图 4. 获取扩展 第二步,在点击“获取扩展”选项后,打开 ...

  4. Deques and Randomized Queues

    1. 题目重述 完成三个程序,分别是双向队列,随机队列,和随机队列读取文本并输出k个数. 2. 分析 2.1 双向队列 题目的性能要求是,操作时间O(1),内存占用最大48n+192byte. 当使用 ...

  5. ElasticSearch基础之批量操作(mget+mbulk)

      在前面的演示中,我们都是基于一次http查询,每次查询都要建立http的三次握手请求,这样比较耗费性能!因此ES给我们提供了基本的批量查询功能,例如如下的查询,注意里面的index是可以任意指明的 ...

  6. 微信小程序开发之页面wxml里面实现循环 wx:for

    js代码: Page({ data:{ upploadimagelist:{},    //上报图片列表 js数组 }}) 后台数据库保存的格式:{"imageList":[{&q ...

  7. C#实现简易ajax调用后台方法

    在当前WEB当中,有些人都会抛弃asp.net的服务器控件,转而使用ajax来进行数据的交互和存储. 当我们大量使用ajax的时候,对于新手而言,肯定会创建很多的ashx或aspx页面,通过拼接参数, ...

  8. 安装APK时SO库的选择策略

    此文已由作者尹彬彬授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 0X0 前言 在Android系统中,当我们安装apk文件的时候,lib目录下的so文件会被解压到app的原 ...

  9. unity sprite怎么获取切割后的图

    学习了一段时间的unity,对里面的组件有一个大致的了解,但是具体操作来说还不是很熟悉,今天看了一片关于unity sprite怎么获取切割后的图的文章,感觉还不错. 假设有一张png/tga图集,导 ...

  10. SpringBoot整合Memached

    一.Memached介绍 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站 ...