题意:有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背包的更多相关文章

  1. hdu 2546 典型01背包

    分析:每种菜仅仅可以购买一次,但是低于5元不可消费,求剩余金额的最小值问题..其实也就是最接近5元(>=5)时, 购买还没有买过的蔡中最大值问题,当然还有一些临界情况 1.当余额充足时,可以随意 ...

  2. ACM HDU Bone Collector 01背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2602 这是做的第一道01背包的题目.题目的大意是有n个物品,体积为v的背包.不断的放入物品,当然物品有 ...

  3. hdu 2955 Robberies (01背包)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 思路:一开始看急了,以为概率是直接相加的,wa了无数发,这道题目给的是被抓的概率,我们应该先求出总的 ...

  4. HDU 2639(01背包求第K大值)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2639 Bone Collector II Time Limit: 5000/2000 MS (Jav ...

  5. hdu 3466 排序01背包

    也是好题,带限制的01背包,先排序,再背包 这题因为涉及到q,所以不能直接就01背包了.因为如果一个物品是5 9,一个物品是5 6,对第一个进行背包的时候只有dp[9],dp[10],…,dp[m], ...

  6. hdu 2955 Robberies 0-1背包/概率初始化

    /*Robberies Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...

  7. 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个 然后归并排序并 ...

  8. HDU——2955 Robberies (0-1背包)

    题意:有N个银行,每抢一个银行,可以获得\(v_i\)的前,但是会有\(p_i\)的概率被抓.现在要把被抓概率控制在\(P\)之下,求最多能抢到多少钱. 分析:0-1背包的变形,把重量变成了概率,因为 ...

  9. HDU 1171Big Event in HDU(转01背包)

    题意: 给你一组数,分成差距最小的两份A,B(A>=B) 分析: 转01背包 注意: 01背包用一维数组 不要用二维 二维数组若是开太大,内存超限,开太小,RE #include "c ...

随机推荐

  1. Socket网络通信编程(一)

    1.学习基本概念.传统的同步阻塞式I/O编程.伪异步IO实现 2.学习基于NIO的同步非阻塞式编程 3.了解基于NIO2.0的异步非阻塞(AIO)编程 1.1 基本概念 Socket又称“套接字”,应 ...

  2. 3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader

    上节的最后我们实现了两个绿色的三角形,而绿色是直接在Fragment Shader中指定的. 这节我们将为这两个三角形进行更加自由的着色——五个顶点各自使用不同的颜色. 要实现这个目的,我们分两步进行 ...

  3. RabbitMQ消息如何100%投递成功(六)

    消息如何保障100%的投递成功? 什么是生产端的可靠性投递? 保障消息的成功发出 保障MQ节点的成功接收 发送端收到MQ节点(Broker)确认应答 完善的消息进行补偿机制(如网络问题没有返回确认应答 ...

  4. DB数据库的基本操作

    启动 MongoDB 服务 sudo service mongodb start 进入 MongoDB 命令行操作界面,在命令行中敲 exit 可以退出.mongo 创建数据库 use db 命令查看 ...

  5. mysql的my.cnf参数详解

    转载[Mysql] MySQL配置文件my.cnf的理解 一.缘由 最近要接手数据库的维护工作,公司首选MySQL.对于MySQL的理解,我认为很多性能优化工作.主从主主复制都是在调整参数,来适应不同 ...

  6. day02-Python基础

    >>> if a > b:... c = a+b... else:... c = a-b...>>> c-1 三元运算: >>> c = a ...

  7. 在一个shell中查看管理 任务(前台和后台)/工作jobs 的命令

    在一个shell中查看管理 任务(前台和后台)/工作jobs 的命令 jobs是在同一个shell环境而言, 才有意义的. 为什么有jobs这个命令? 是因为, 如果从cmd line运行gui程序时 ...

  8. 深入探讨 Python 的 import 机制:实现远程导入模块

        深入探讨 Python 的 import 机制:实现远程导入模块 所谓的模块导入( import ),是指在一个模块中使用另一个模块的代码的操作,它有利于代码的复用. 在 Python 中使用 ...

  9. (二)Maven之坐标和依赖

    目录 坐标 依赖 目录 坐标 引言: 坐标是依赖管理的基础,是构建的唯一标识. 组成元素: 使用groupId.artifactId.version.packaging.classifier标签即可定 ...

  10. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_09 序列化流_3_对象的反序列化流_ObjectInputStream

    声明了IO异常,这里还是红色的 转换为Person对象