题意:有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. java配置环境变量 jdk1.8

    1.首先第一步安装JDK window系统安装java 下载JDK 首先我们需要下载java开发工具包JDK,下载地址:http://www.oracle.com/technetwork/java/j ...

  2. VS 2010内存泄漏检测

    控制台程序在启动时调用 _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 程序正常退出后会打印内存泄漏信息. MFC程序不用 ...

  3. 查看磁盘和文件的使用情况df和du

    df, du: disk filesystem, disk usage. df : 查看一级目录的使用情况, df -h du: 则是可以查看目录或者某个文件的占用磁盘空间的情况, du -h: 使用 ...

  4. python-网络编程requests模块

    urllib模块去请求的确比较麻烦,需要不断的encode和decode:而requests模块就比较方便了,它是基于requests模块开发的第三方模块,安装简单只需要  pip install r ...

  5. mysql_Qcahce

    .cpu mem disk 如果是固态硬盘ssd那就是高速公路 火箭 高铁 普通公路 mysql 配置文件:windows 下 mysql.ini linux:my.cnf lamp路径:/opt/l ...

  6. 升级到mysql5.7无法启动问题解决

    漏洞扫描,老项目升级到5.7位成功,启动发现报错:unknown option log_error 线备份my.cnf配置文件, 猜测应该是写法有问题,先把log_error  改成log #log_ ...

  7. ssm项目的创建思路

    ·DAO层: 代码:pojo.映射文件.接口文件——Mybatis逆向工程自动生成 配置:ApplicationContext-dao.xml——数据源.连接池.会话工厂.mapper包扫描 ·Ser ...

  8. [Usaco2014 Feb] Roadblock

    有一个无向图,共N个节点,编号1至N,共M条边.FJ在节点1,它想到达节点N.FJ总是会选择最短路径到达节点N .作为捣蛋的奶牛Bessie,它想尽量延迟FJ到达节点N的时间,于是Bessie决定从M ...

  9. 20191105 《Spring5高级编程》笔记-第9章

    第9章 事务管理 一些名词: 2PC(2 Phase Commit) XA协议 JTS(Java Transaction Service) JCA(Java EE Connector Architec ...

  10. [Git] 008 status 与 commit 命令的补充

    本文的"剧情"承接 [Git] 007 三棵树以及向本地仓库加入第一个文件 1. 对 "status" 的补充 1.1 "status" 有 ...