dp

分组背包

狂风中的少年 提交于 2019-11-27 07:53:33
分组背包 分组背包其实就是通过更改和增加枚举顺序来把01背包中的状态(第i个j重量时的最大价值转化为第i组j重量时的最大价值)。 但是要注意的就是枚举顺序一定要正确。 #include <bits/stdc++.h> using namespace std; int n, m, k; int a[110][1010]; int w[100100], v[1010010], dp[101000]; int main() { scanf("%d%d", &m, &n); for (int i = 1; i <= n; i++) { int b; scanf("%d%d%d", &w[i], &v[i], &b); k = max(k, b); a[k][++a[k][0]] = i; } for (int i = 1; i <= k; i++) for (int c = m; c >= 0; c--) //这个一定要在外面 ,因为如果在里面的话,则dp[v]该状态包括i组的其他成员。但是如果在外面, 则dp[c-w[a[i][j]]]其实是上一组的dp[i-1][c-w[a[i][j]]],所以要放在外面。 for (int j = 1; j <= a[i][0]; j++) if (c - w[a[i][j]] >= 0) dp[c] = max(dp[c], dp[c - w[a

2019暑假集训 不要62

我与影子孤独终老i 提交于 2019-11-27 07:35:27
题目描述 杭州人称那些傻乎乎粘嗒嗒的人为 62(音:laoer)。 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。 不吉利的数字为所有含有4或62的号码。例如:62315,73418,88914都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。 你的任务是,对于每次给出的一个牌照区间号,推断出交管局今后又要实际上给多少辆新的士车上牌照了。 输入 输入的都是整数对n,m,如果遇到都是0的整数对,则输入结束。 输出 对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。 样例输入 1 100 0 0 样例输出 80 又是裸的数位dp,每次判断当前是不是4,当前与前一位是不是62即可上代码 #include<iostream> #include<cstdio> #include<cstring> using namespace std; int digit[15],dp[105][105],n=1,m=1,idx; int DP(int pos,int statu,int limit) { if(!pos)return 1; if(!limit&&~dp[pos][statu])return dp[pos]

P1776 宝物筛选 多重背包

和自甴很熟 提交于 2019-11-27 06:40:20
题目描述 终于,破解了千年的难题。小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物……这下小FF可发财了,嘎嘎。但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝物。看来小FF只能含泪舍弃其中的一部分宝物了……小FF对洞穴里的宝物进行了整理,他发现每样宝物都有一件或者多件。他粗略估算了下每样宝物的价值,之后开始了宝物筛选工作:小FF有一个最大载重为W的采集车,洞穴里总共有n种宝物,每种宝物的价值为v[i],重量为w[i],每种宝物有m[i]件。小FF希望在采集车不超载的前提下,选择一些宝物装进采集车,使得它们的价值和最大。 输入格式 第一行为一个整数N和w,分别表示宝物种数和采集车的最大载重。 接下来n行每行三个整数,其中第i行第一个数表示第i类品价值,第二个整数表示一件该类物品的重量,第三个整数为该类物品数量。 输出格式 输出仅一个整数ans,表示在采集车不超载的情况下收集的宝物的最大价值。 ============================================================================================================================================================== 一些遇到的问题 对于二进制的理解。 不是完全背包

0-1背包判断物品能否组合问题

谁说我不能喝 提交于 2019-11-27 05:47:41
题目描述 小米之家是成人糖果店。里面有很多便宜,好用,好玩的产品。中秋节快到了,小米之家想给米粉们准备一些固定金额大礼包。对于给定的一个金额,需要判断能不能用不同种产品(一种产品在礼包最多出现一次)组合出来这个金额。聪明的你来帮帮米家的小伙伴吧。 输入描述: 输入 N (N 是正整数, N <= 200) 输入 N 个价格p(正整数, p <= 10000)用单空格分割 输入金额 M(M是正整数,M <= 100000 ) 输出描述: 能组合出来输出 1 否则输出 0 示例1 输入 复制 6 99 199 1999 10000 39 1499 10238 输出 复制 1 #include <iostream> #include<vector> using namespace std; int main(){ int N; vector<int> Input; int M; scanf("%d",&N); for(int i = 0;i < N;i ++){ int tmp; scanf("%d",&tmp); Input.push_back(tmp); } scanf("%d",&M); vector<bool> dp(M + 1,false); dp[0] = true; for(int i = 0;i < Input.size();i ++){ for(int j = M;j

HDU 6558 The Moon(概率dp)

ⅰ亾dé卋堺 提交于 2019-11-27 04:07:01
题意:一个初始中奖率q=2%,每次玩一局游戏,如果游戏赢了就抽奖,没抽到就q+2,然后继续玩游戏,如果游戏输了就q+1.5。问玩的游戏局数的期望,并且中奖率最高为100% 题解:初始中奖率为q%,输入的是游戏的获胜概率p%,dp[i]为获奖概率为 i 时的期望。因为q%最高为100%,所以初始状态为dp[100],但是因为如果游戏输了的话是p+1.5,而数组的下标是不能用小数的,所以我们整体扩大2倍,初始状态设为dp[200]。 当q = 100%的时候,显然dp[200] = 1 / p。转移方程 d p [ q ] = p ⋅ ( 1 − q ) ⋅ d p [ m i n ( q + 4 , 2 0 0 ) ] + ( 1 − p ) d p [ m i n ( q + 3 , 2 0 0 ) ] + 1, 其中1是当前局 p⋅(1−q)⋅dp[min(q+4,200)]为游戏获胜但是未中奖的期望 (1−p)dp[min(q+3,200)]为游戏失败的期望,三者和即为概率为q时的期望 #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<stack> #include<cstdlib> #include<queue> #include

P1049 装箱问题

Deadly 提交于 2019-11-27 03:33:26
链接 P1049 装箱问题 感想 这道题就是在0-1背包的基础上加了一点,就是0-1背包是需要装的东西最多(价值最大),但是这题是要求剩余的空间最少,那么首先dp数组里必然是用剩余的空间作为dp所存的内容,转移方程也随之变成了: if(dp[j-item[i]]-item[i]>=0) { dp[j] = min(dp[j], dp[j-item[i]]-item[i]); } code # include <algorithm> # include <bits/stdc++.h> # include <stdlib.h> # include <stdio.h> # include <iostream> using namespace std ; const int maxn = 1005 ; int item [ 30 + 5 ] ; int dp [ 20000 + 5 ] ; int main ( ) { # ifdef LOCAL freopen ( "C:\\Users\\hsxny\\Desktop\\in.txt" , "r" , stdin ) ; # endif int V , N ; scanf ( "%d%d" , & V , & N ) ; for ( int i = 0 ; i < N ; i ++ ) { scanf ( "%d" , & item [

hdu2089 不要62(数位dp)

孤者浪人 提交于 2019-11-27 03:29:45
不要62 本题大意:不吉利数字为62和4,求给定区间内的不吉利数的个数。 最为基础的数位dp入门题,不过本弱鸡水平太低,对着函数死看看不懂,只能当作模版用了,solve(x)表示x以内的不吉利数字的个数,用右区间减去左区间即可。 #include <iostream> #include<cstdio> #include <algorithm> #include <string> #include <cstring> #include <map> #include <set> #include <stack> #include <cmath> #include <queue> #include <vector> #define init(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);} using namespace std; typedef long long ll; int a[20]; ll dp[20][2]; ll dfs(int pos, int pre, int state, bool limit) { if(pos==-1) return 1; if(!limit && dp[pos][state]!=-1) return dp[pos][state]; int up=limit?a[pos]:9; ll

Comet OJ - Contest #8

前提是你 提交于 2019-11-27 01:21:49
---恢复内容开始---      Comet OJ - Contest #8参赛总结—— 林荫 本人还是一如既往的菜。 Comet OJ - Contest #X属于ACM赛制 六道题目难度从入门到金牌递增   本次总结给出T3,4分析与解法(5,6以后填坑)    T3:符文能量 1000ms,256MB 题目描述 米薇女王万万没有想到考德威尔男爵的真实意图。她的脑海里浮现出莱里亚的秀美山河,可惜再也回不去了。 不过所幸的是,她还有着军队和重整山河的勇气。雷纳德为米薇女王呈上了 nn n 块符文石。符文石可以帮助你更好的战斗。每个符文石拥有能量,米薇可以挑选类型相近的符文石融合并释放出能量。 形象的,我们可以把每个符文石 PiP_i P i ​ 描述成一个二元组 (ai,bi)(a_i,b_i) ( a i ​ , b i ​ ) 。对于两个相邻的符文石 PiP_i P i ​ 与 Pi+1 P_{i+1} P i + 1 ​ ,可以把他们融合为 (ai,bi+1)(a_i,b_{i+1}) ( a i ​ , b i + 1 ​ ) 并释放出 ai+1∗bia_{i+1}*b_i a i + 1 ​ ∗ b i ​ 的能量。融合完的符文石会替换掉原本的两个二元组,出现在他们的位置上。米薇希望把所有的 nn n 个符文石融合成 11 1 个符文石

322.零钱兑换

孤者浪人 提交于 2019-11-26 23:53:46
思路 dp问题,空间换时间,递推公式(初始化+转移方程), F(S) = F(S-C) + 1 # S 代表总额(amount), F(S)代表最少兑换次数,C代表兑换的最后一个面值,其中 S为0时,F(S) = 0, 零钱数组为空时,F(S)=-1. 解法 暴力穷举,回溯 public int coinChange(int[] coins, int amount) { return coinChange(0, coins, amount); } private int coinChange(int coinsIndex, int[] coins, int amount) { if (amount == 0) { return 0; } if (coinsIndex == coins.length) { return -1; } int min = Integer.MAX_VALUE; int maxNum = amount / coins[coinsIndex]; for (int num = 0; num <= maxNum; num++) { int otherNums = coinChange(coinsIndex + 1, coins, amount - num * coins[coinsIndex]); if(otherNums != -1) { min = Math