没有找零 状压dp
没有找零 状压dp
约翰到商场购物,他的钱包里有K(1 <= K <= 16)个硬币,面值的范围是1..100,000,000。约翰想按顺序买 N个物品(1 <= N <= 100,000),第i个物品需要花费c(i)块钱,(1 <= c(i) <= 10,000)。在依次进行的购买N个物品的过程中,约翰可以随时停下来付款,每次付款只用一个硬币,支付购买的内容是从上一次支付后开始到现在的这些所有物品(前提是该硬币足以支付这些物品的费用)。不幸的是,商场的收银机坏了,如果约翰支付的硬币面值大于所需的费用,他不会得到任何找零。请计算出在购买完N个物品后,约翰最多剩下多少钱。如果无法完成购买,输出-1。
如果我们枚举k的全排列是肯定超时的。显然对于一种硬币的选择方案,尽可能选更多的物品更优,没有必要枚举全排列。所以\(f[i]\)表示当前选硬币的状态为\(i\),在第i个物品处,用第j个硬币能到达的最远处。那么转移方程为\(f[i]=f[j]+a[f[j]][k]\),k可以通过i,j判断出来。别忘记要预处理a。那么时间复杂度则为\(O(knlog_2n+2^kn)\)。
感觉状压dp就是在dp减少无用状态的前提下贪心而已。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5, maxk=20;
int k, n, coins[maxn], things[maxn], pre[maxn];
// pre:物品的前缀和
int a[maxn][maxk]; //在第i个位置,用第j个硬币的能到达的地方。
int f[int(1e6)]; //一个状态最远能到达的地方
int calc(int now){
int re=0;
for (int i=k; i>0; --i){
re+=(1-(now&1))*coins[i];
now>>=1;
}
return re;
}
int main(){
scanf("%d%d", &k, &n);
for (int i=1; i<=k; ++i) scanf("%d", &coins[i]);
for (int i=1; i<=n; ++i){
scanf("%d", &things[i]);
pre[i]=pre[i-1]+things[i];
}
int t, t2;
for (int i=1; i<=n; ++i)
for (int j=1; j<=k; ++j){
t=pre[i-1]+coins[j];
a[i][j]=upper_bound(pre+i, pre+n+1, t)-pre-i;
}
for (int i=0; i<(1<<k); ++i){
t=1;
for (int j=k; j>=1; --j){ //枚举前一个状态
if (t&i){
t2=i-t;
f[i]=max(f[i], f[t2]+a[f[t2]+1][j]);
}
t<<=1;
}
}
int ans=0; bool flag=false;
for (int i=0; i<(1<<k); ++i){
if (f[i]==n&&calc(i)>ans) ans=calc(i);
if (f[i]==n) flag=true;
}
printf("%d", flag?ans:-1);
return 0;
}
没有找零 状压dp的更多相关文章
- [BZOJ3312][USACO]不找零(状压DP)
Description 约翰带着 N 头奶牛在超市买东西,现在他们正在排队付钱,排在第 i 个位置的奶牛需要支付 Ci元.今天说好所有东西都是约翰请客的,但直到付账的时候,约翰才意识到自己没带钱,身上 ...
- Codeforces 1383C - String Transformation 2(找性质+状压 dp)
Codeforces 题面传送门 & 洛谷题面传送门 神奇的强迫症效应,一场只要 AC 了 A.B.D.E.F,就一定会把 C 补掉( 感觉这个 C 难度比 D 难度高啊-- 首先考虑对问题进 ...
- FZU 2093 找兔子 状压DP
题目链接:找兔子 n的范围是[1, 15],可以用0 到 (1<<n)-1 的数表示全部状态,用dp[i] = t表示到达状态i的最少时间是t,对于每个点,如果它能到达的所有点在t秒时都已 ...
- [luoguP3092] [USACO13NOV]没有找零No Change(状压DP + 二分)
传送门 先通过二分预处理出来,每个硬币在每个商品处最多能往后买多少个商品 直接状压DP即可 f[i]就为,所有比状态i少一个硬币j的状态所能达到的最远距离,在加上硬币j在当前位置所能达到的距离,所有的 ...
- Codeforces 1225G - To Make 1(bitset+状压 dp+找性质)
Codeforces 题目传送门 & 洛谷题目传送门 还是做题做太少了啊--碰到这种题一点感觉都没有-- 首先我们来证明一件事情,那就是存在一种合并方式 \(\Leftrightarrow\) ...
- ZOJ3802 Easy 2048 Again (状压DP)
ZOJ Monthly, August 2014 E题 ZOJ月赛 2014年8月 E题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?proble ...
- LGTB与序列 状压dp
考试一看我就想到了状压dp.当时没有想到素数,以为每一位只有0~9这些数,就开始压了.后来发现是小于30,然后改到了15,发现数据一点不给面子,一个小点得数都没有,完美爆零.. 考虑到bi最多变成58 ...
- 树形DP和状压DP和背包DP
树形DP和状压DP和背包DP 树形\(DP\)和状压\(DP\)虽然在\(NOIp\)中考的不多,但是仍然是一个比较常用的算法,因此学好这两个\(DP\)也是很重要的.而背包\(DP\)虽然以前考的次 ...
- 状压DP总结
状态压缩就是将一行的状态压成一个二进制数,这个数的二进制形式反映了这一行的情况 比如0100111的意义为:这一排的第一个数没被使用,第二个被占用了,第三四个没被占用,第五六七个被占用 我们知道位运算 ...
随机推荐
- 关键字volidate和transient(转)
Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...
- Android中高效的显示图片之二——在非UI线程中处理图片
在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...
- User-Agent 及其构造
url = ... user_agent = ... headers = {'User-Agent' : user_agent} req = requests.request(url=url, hea ...
- ONVIF Device Manager v2.2.146
对接ONVIF使用软件,用于对接支持onvif协议的IPC厂家设置 http://download.csdn.net/detail/li_dabo/9761415
- POJ2420:A Star not A Tree?
我对模拟退火的理解:https://www.cnblogs.com/AKMer/p/9580982.html 我对爬山的理解:https://www.cnblogs.com/AKMer/p/95552 ...
- Poj 1552 Doubles(水题)
一.Description As part of an arithmetic competency program, your students will be given randomly gene ...
- AI-Info-Micron-Menu:Products
ylbtech-AI-Info-Micron-Menu:Products 我们制造业界最广泛的存储器和存储技术产品组合:DRAM,NAND,NOR和3D XPoint™存储器. 凭借紧密的行业合作伙伴 ...
- 数据库管理员(Database Administrator,简称DBA)基本知识:
数据库管理员(Database Administrator,简称DBA)基本知识: 一.数据库基础 1. 数据抽象:物理抽象.概念抽象.视图级抽象,内模式.模式.外模式 2. SQL语言包括数据定义. ...
- spring--设置注入VS构造注入
1.在传统的程序设计中,调用亲自创建被调用者的实例,即由程序控制“对象之间的依赖关系”,这种方式的耦合度比较高:控制反转就是将由程序控制的“对象间的依赖关系”转交给Ioc容器来进行控制,被调用者的实例 ...
- JVM类加载(2)—连接
2.连接 连接就是将已经加载到内存中的类的二进制数据合并到Java虚拟机的运行时环境中去,加载阶段尚未完成,连接阶段可能已经开始.连接阶段包含验证.准备.解析过程. 2.1.验证 验证.class文件 ...