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 ...
随机推荐
- 【JOI2017春季合宿】Port Facility
http://uoj.ac/problem/356 题解 思路和\(NOIP\)双栈排序差不多. 对于两个元素,若\(l_1<l_2<r_1<r_2\)那么它们不能在一个栈里,我们连 ...
- 深入JavaWeb技术世界15:深入浅出Mybatis基本原理
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- RTP/RTSP编程
https://blog.csdn.net/pu1030/article/details/7619908 http://blog.chinaunix.net/uid-27875-id-5017161. ...
- 了解SELlinux
selinux是mac: mandatory access control. 强制访问控制. 是经过了20年的mac研究基础上开发的安全子系统. 访问控制分为三种: dac: di'scretiona ...
- HTML - form 表单提交
form 表单提交 数据发送 disabled:不发送 display_none:发送 type_hidden:发送 readonly:发送 测试 html: <!DOCTYPE html> ...
- 使用GOGS搭建自己的Git托管
大家在开发中一般使用的git服务都是公司搭建好的,或者就是直接用gayhub提供的免费的仓库 如果想搭建一个自己的仓库的话怎么弄,这里给大家安利一款开箱即用的git托管服务:gogs. gogs是基于 ...
- VMware 虚拟化编程(10) — VMware 数据块修改跟踪技术 CBT
目录 目录 前文列表 数据块修改跟踪技术 CBT 为虚拟机开启 CBT CBT 修改数据块偏移量获取函数 QueryChangedDiskAreas changeId 一个 QueryChangedD ...
- Java ——变量类型
变量声明 int a, b, c; // 声明三个int型整数:a. b.c int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值 byte z = 22; // 声明并初始 ...
- 工具 - MSF
#ms17- use auxiliary/scanner/smb/smb_ms17_010 - exploit use exploit/windows/smb/ms17_010_eternalblue ...
- linux eclipse 下出现undefined reference ***,在使用boost库时出现的问题
直接在eclipse下添加boost_system就可以了,这个文件有可能在库中找不到,或者名字不一样,直接使用这个名字就可以了,在setting 下