HDU-3810 超大容量01背包
题意:有n堆野兽,每堆野兽屠杀完完需要花费ti时间,可以增加金钱gi,敌法师有瞬移技能,可以从某堆野兽移到另一堆野兽,题目有给定从哪堆可以移到哪堆。最后问在满足打的金钱多余m的情况下的最少时间。数据范围:1 <= T <= 50 , 1 <= N <= 50(怪物数量), 1 <= Ti <= 10000000(时间),1 <= M, Gi <= 1000000000(要求金钱/每组野怪金钱)。
解法:题解参考https://www.cnblogs.com/Konjakmoyu/p/5962062.html?utm_source=itdadao&utm_medium=referral。这位大佬的。
看到题目很明显的0/1背包,但是看到数据范围发现是个超大容量的01背包,那么我们就肯定不能使用DP来解决这个问题了。我们注意到虽然容量很大但是物品数量却非常小,暗示我们可以用一些比较暴力一些的办法。我们想办法用别的数据结构模拟解01背包的过程,于是就用到 优先队列模拟01背包做DP(为什么要用优先队列,下面会讲到)。
假定用q0队列表示上一行,q1队列表示当前行。那么对于当前物品i,我们就从上一行状态q0转移到q1,那么也就是枚举q0的每个状态然后对物品i有两种选择:选或者不选,想起来很简单。可惜这样会获得MLE/TLE。为什么?因为每次都选和不选就相当于暴搜了,时间复杂度是2^50次方肯定不行。我们得剪枝,最关键的是其实同一时间的状态有很多都是没有用的,钱比别人少时间却还比别人多,这样的状态没有用!!!于是我们要用到优先队列,金钱多的排前面然后同样多钱的时间少的排前面,那么我们筛选本次拓展出来的状态哪些是有用的?因为我们优先队列已经是按金钱多排前面,所以此时时间单调减的状态才有用!!!
于是加上上面这个大剪枝时候我们再加些容易想到的小细节就可以获得AC了。
细节详见代码:
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=;
const int INF=0x7fffffff;
int n,m,k,w[N],v[N],fa[N];
struct dat{
int x,y; //时间,金钱
bool operator < (const dat &rhs) const {
return y<rhs.y || y==rhs.y && x>rhs.x;
}
};
priority_queue<dat> q1,q2; int getfa(int x) { return x==fa[x] ? x : fa[x]=getfa(fa[x]); } int main()
{
int T,kase=; scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) fa[i]=i;
for (int i=;i<=n;i++) {
scanf("%d%d%d",&w[i],&v[i],&k);
for (int j=;j<=k;j++) {
int x; scanf("%d",&x);
fa[getfa(x)]=getfa(i);
}
} int ans=INF;
for (int i=;i<=n;i++)
if (getfa(i)==i) { //一个联通块的物品
while (!q1.empty()) q1.pop();
while (!q2.empty()) q2.pop();
q1.push((dat){,});
for (int j=;j<=n;j++) { //j个物品
if (getfa(j)!=i) continue;
while (!q1.empty()) {
dat u=q1.top(); q1.pop();
if (u.y>=m) { ans=min(ans,u.x); continue; } //剪枝1
if (u.x>=ans) continue; //剪枝2
q2.push(u); //不选
int x=u.x+w[j],y=u.y+v[j];
if (y>=m) { ans=min(ans,x); continue; } //剪枝1
if (x>=ans) continue; //剪枝2
q2.push((dat){x,y}); //选
}
int Min=INF;
while (!q2.empty()) {
dat u=q2.top(); q2.pop();
if (u.x<Min) q1.push(u),Min=u.x; //剪枝3:钱比别人少时间却还比别人多,这样的状态没有用
}
}
}
if (ans==INF) printf("Case %d: Poor Magina, you can't save the world all the time!\n",++kase);
else printf("Case %d: %d\n",++kase,ans);
}
return ;
}
HDU-3810 超大容量01背包的更多相关文章
- hdu 2546 典型01背包
分析:每种菜仅仅可以购买一次,但是低于5元不可消费,求剩余金额的最小值问题..其实也就是最接近5元(>=5)时, 购买还没有买过的蔡中最大值问题,当然还有一些临界情况 1.当余额充足时,可以随意 ...
- ACM HDU Bone Collector 01背包
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 这是做的第一道01背包的题目.题目的大意是有n个物品,体积为v的背包.不断的放入物品,当然物品有 ...
- hdu 2955 Robberies (01背包)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 思路:一开始看急了,以为概率是直接相加的,wa了无数发,这道题目给的是被抓的概率,我们应该先求出总的 ...
- HDU 2639(01背包求第K大值)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 Bone Collector II Time Limit: 5000/2000 MS (Jav ...
- hdu 3466 排序01背包
也是好题,带限制的01背包,先排序,再背包 这题因为涉及到q,所以不能直接就01背包了.因为如果一个物品是5 9,一个物品是5 6,对第一个进行背包的时候只有dp[9],dp[10],…,dp[m], ...
- hdu 2955 Robberies 0-1背包/概率初始化
/*Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- HDU 2639 (01背包第k优解)
/* 01背包第k优解问题 f[i][j][k] 前i个物品体积为j的第k优解 对于每次的ij状态 记下之前的两种状态 i-1 j-w[i] (选i) i-1 j (不选i) 分别k个 然后归并排序并 ...
- HDU——2955 Robberies (0-1背包)
题意:有N个银行,每抢一个银行,可以获得\(v_i\)的前,但是会有\(p_i\)的概率被抓.现在要把被抓概率控制在\(P\)之下,求最多能抢到多少钱. 分析:0-1背包的变形,把重量变成了概率,因为 ...
- HDU 1171Big Event in HDU(转01背包)
题意: 给你一组数,分成差距最小的两份A,B(A>=B) 分析: 转01背包 注意: 01背包用一维数组 不要用二维 二维数组若是开太大,内存超限,开太小,RE #include "c ...
随机推荐
- window cmd 命令行下创建文件夹和文件
新建文件夹命令: makedir 文件名 新建文件命令: type null> 文件名.文件类型 链接
- Spring Cloud架构教程 (五)服务网关(过滤器)
过滤器的作用 通过上面所述的两篇我们,我们已经能够实现请求的路由功能,所以我们的微服务应用提供的接口就可以通过统一的API网关入口被客户端访问到了.但是,每个客户端用户请求微服务应用提供的接口时,它们 ...
- 12 Django组件-form组件
知识预览 forms组件 forms组件 校验字段功能 针对一个实例:注册用户讲解. 模型:models.py class UserInfo(models.Model): name=models.Ch ...
- Maps.newHashMap 和 new HashMap的区别
区别: (1)Map<String, Object> result = new HashMap<String,Object>(); 这种是java原生API写法,需要你手动加泛 ...
- tab下图表展示宽高为0的问题
tab下,默认展示第一个tab(最新订阅),第二个tab是echarts,需要动态获取父级div的宽高并赋值到图表的DOM的宽高.在实际开发过程中,发现无论如何延迟处理,或者mounted,第二个ta ...
- ImageView的src与background及ScaleType
1 概述 开发中经常使用Imageview的src和background属性,从字面上看src是路径,background是背景.二者都可以显示drawable或者颜色.设置drawable图片资源时 ...
- mysql依据某一张表的字段,查询出对应的表所在的数据库
表太多,只记得这个表有一个mygame的字段,但是并不知道这张表在那个数据库下,只能根据这个字段查找对应的表和所在数据库 select table_schema,table_name from inf ...
- Js基本类型中常用的方法总结
1.数组 push() -----> 向数组末尾添加新的数组项,参数为要添加的项,返回值是新数组的长度,原数组改变: pop() -----> 删除数组末尾的最后一项,参数无,返回值是删除 ...
- 简述Vue中的计算属性
1.什么是计算属性 如果模板中的表达式存在过多的逻辑,那么模板会变得臃肿不堪,维护起来也异常困难,因此为了简化逻辑出现了计算属性: <template> <div id=" ...
- URIs, URLs, and URNs
首先,URI,是uniform resource identifier,统一资源标识符,用来唯一的标识一个资源.而URL是uniform resource locator,统一资源定位器,它是一种具体 ...