没有找零 状压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的意义为:这一排的第一个数没被使用,第二个被占用了,第三四个没被占用,第五六七个被占用 我们知道位运算 ...
随机推荐
- node.js+express验证码的实现
安装ccap库 npm install ccap var ccap = require(); var captcha = ccap({ width:190, height:50, offset:30, ...
- 20179215《Linux内核原理与分析》第一周作业
一.Linux介绍 我们现在很常见Windows系统,对于Linux则显得尤为陌生.当然我也不例外,初识Linux过程中遇到一些困惑,但我也在实验的同时通过不断查找资料与实践中慢慢解决问题.那么下面我 ...
- 第k小和(搜索)
Description [问题描述] 从n个数中选若干(至少1)个数求和,求所有方案中第k小的和(和相同但取法不同的视为不同方案).[输入格式] 第一行输入2个正整数n,k. 第二行输入这 ...
- 51nod 1486 大大走格子——容斥
题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1486 已知起点到某个障碍点左上角的所有点的不经过障碍的方案数,枚举 ...
- bzoj 5120 无限之环 & 洛谷 P4003 —— 费用流(多路增广SPFA)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5120 https://www.luogu.org/problemnew/show/P4003 ...
- 通用RowMapper封装查询结果到自定义类中
package object; import java.lang.reflect.Field;import java.sql.ResultSet;import java.sql.SQLExceptio ...
- java继承示例
package day07; class Fu { int num = 5; } class Zi extends Fu { int num =7; void show() { int num =9; ...
- uva 512
1. 问题 不知道怎么存储操作 看代码注释,else if等 2. 代码 #include <iostream> #include <stdio.h> #include < ...
- HttpApplication 对象的创建过程及HttpModule过滤器的内部实现过程
最近通过Reflector学习了一下asp.net内部的原理,做做笔记,方便以后查阅. 先看下HttpApplication 对象的创建过程 从IHttpHandler applicationInst ...
- 使用python+requests对接口进行测试
import unittestimport requestsimport json class Login(unittest.TestCase): def setUp(self): self.base ...