题意:

  有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. Ubuntu12.04下安装VirtualBox

    目录: 安装虚拟机VirtualBox 虚拟机VirtualBox安装win7全过程 虚拟机共享文件夹.U盘 一.安装虚拟机VirtualBox VirtualBox下载地址:https://www. ...

  2. OpenService 打开一个已经存在的服务

    SC_HANDLE WINAPI OpenService( _In_ SC_HANDLE hSCManager, _In_ LPCTSTR lpServiceName, _In_ DWORD dwDe ...

  3. 读取关联数据(EF Core2.1.1)

    对象-关系映射框架比如EF有三种 方式使用 模型中的导航属性来加载关联数据. 一..Lazy Loading.(关联数据在访问导航属性时被透明的加载,不需要特别的代码,自动的加载) 当一个实体第一次读 ...

  4. Asset Catalog Help (四)---Adding an iOS App Icon Set or Launch Image Set

    Adding an iOS App Icon Set or Launch Image Set Organize different resolutions of your app icons and ...

  5. Quartz实现定期运行程序(Java)

    package Quartz; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.Job; imp ...

  6. vector 大小

    vector定义以后就最好确定大小resize(),否则在vector析构时可能出现 "double free or corruption"这样的错误

  7. UVaLive 6854 City (暴力)

    题意:给定一个 n*m 的矩阵,表示有多少条道路与它相连,其中有一个-1,表示未知,道路只能横着和竖着,求-1处的值. 析:根据题意可知,一个点,与其他周围的四个点都可能相连的,也就是说肯定有共用道路 ...

  8. 树莓派也跑Docker和.NET Core

    树莓派是什么 树莓派就是一个卡片大小的迷你电脑. 安装系统 有了电脑,我们当然得先安装系统. 系统下载 https://www.raspberrypi.org/downloads/raspbian/ ...

  9. 浏览器插件--TamperMonkey

    可以在此插件中添加一些脚本: 1,破解VIP会员视频集合,目前里里面的 “石头解析“,”无名小站“,”vip看看 ”可以解析爱奇艺等的视屏网站的会员视频 // ==UserScript== // @n ...

  10. BackgroundWorker的使用一二(可视化编程,开始后台工作,报告进度,取消后台工作等)

    C# 提供了BackgroundWorker功能非常强大,可以将某项工作放到后台运行,可以让后台报告进度,可以取消后台工作...... BackgroundWorker的上述功能是通过 1. 三个主要 ...