没有找零 状压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的意义为:这一排的第一个数没被使用,第二个被占用了,第三四个没被占用,第五六七个被占用 我们知道位运算 ...
随机推荐
- javaScript-基础篇(二)
1.DOM概念 文档对象模型DOM(Document Object Model)定义访问和处理HTML文档的标准方法.DOM 将HTML文档呈现为带有元素.属性和文本的树结构(节点树) 将HTML代码 ...
- L99
You're not obligated to win. You're obligated to keep trying.你不一定要获胜,但你必须不断尝试.He announced an expans ...
- xxx was built without full bitcode" 编译错误解决
xxx was built without full bitcode" 编译错误解决 iOS 打包上线 All object files and libraries for bitcode ...
- C语言小程序(八)、统计字母个数
这么简单的程序本不应贴在这里,但每写一篇博客,积分涨10分,距离摆脱千里之外的排名又进一步,相当于刷榜了,哈哈! #include <stdio.h> #include <strin ...
- BZOJ5289:[HNOI2018]排列
我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...
- JavaScript下的进制转换
JavaScript下的进制转换 //十进制转其他进制 var num = 99; console.log('十进制: ', num); console.log('八进制:', (num).toStr ...
- Poj 3903 Stock Exchange(LIS)
一.Description The world financial crisis is quite a subject. Some people are more relaxed while othe ...
- Python:内置函数makestrans()、translate()
转于:https://blog.csdn.net/u014351782/article/details/46740297 博主:夜-feng 一.makestrans() 格式: str.maketr ...
- java 代码。= -=
package com.da; //toString()方法, //Object类重写... public class ty { private String name; private int ag ...
- binlog之二:怎么样安全删除mysql下的binlog日志
删除binlog方法 第一种方法: mysql> show binary logs; 查看mysql bin-log日志,除了这个以外的,其它都可以使用删除.mysql> purge bi ...