NOIP2018提高组金牌训练营——动态规划专题
NOIP2018提高组金牌训练营——动态规划专题
https://www.51nod.com/Live/LiveDescription.html#!#liveId=19
多重背包
二进制优化转化成01背包就好了
一只猪走进了一个森林。很凑巧的是,这个森林的形状是长方形的,有n行,m列组成。我们把这个长方形的行从上到下标记为1到n,列从左到右标记为1到m。处于第r行第c列的格子用(r,c)表示。
刚开始的时候猪站在(1,1),他的目标是走到(n,m)。由于猪回家心切,他在(r,c)的时候,只会往(r+1,c)或(r,c+1)走。他不能走出这个森林。
这只猪所在的森林是一个非同寻常的森林。有一些格子看起来非常相似,而有一些相差非常巨大。猪在行走的过程中喜欢拍下他经过的每一个格子的照片。一条路径被认为是漂亮的当且仅当拍下来的照片序列顺着看和反着看是一样的。也就是说,猪经过的路径要构成一个回文。
数一数从(1,1)到(n,m)有多少条漂亮路径。答案可能非常巨大,请输出对 $10^9+7$ 取余后的结果。
样例解释:有三种可能
收起
输入
- 单组测试数据。
- 第一行有两个整数 n,m (1≤n,m≤500),表示森林的长和宽。
- 接下来有n行,每行有m个小写字母,表示每一个格子的类型。同一种类型用同一个字母表示,不同的类型用不同的字母表示。
输出
- 输出答案占一行。
输入样例
- 3 4
- aaab
- baaa
- abba
输出样例
- 3
- 注意到500分数据范围,考虑n三方的算法
发现回文非常难判断,可能要记录整个路径,不现实
所以从两端开始搜
f[x1][y1][x2][y2]表示从(1, 1)到(x1,y1),从(n, m)走到(x2, y2)
的方案数。这样就很好转移了,有四个方程,分别对应从(1, 1)往下还是往右
(n, m)往上还是往左
但是发现这样会炸空间,炸时间
那么显然有x1 + y1 = x2 + y2
那么f[x1][y1][x2]可以省去一维
但这样会炸空间
怎么办?
可以这样设计f[step][x1][x2], step = x1 + y1
有什么区别?
这样的话step的这一维只和step-1有关
所以可以用滚动数组优化掉一维的空间。
那么这道题就完美的解决了。
代码略……
1412 AVL树的种类
https://www.51nod.com/Challenge/Problem.html#!#problemId=1412&judgeId=0
输入
- 一行,包含一个整数n。 (0 < n <= 2000)
输出
- 一行表示结果,由于结果巨大,输出它对1000000007取余数的结果。
输入样例
- 10
输出样例
- 60
- 显然状态和节点数和高度有关,
设f[n][d]为有n个节点,高度为d的方案数
那么对于高度d,考虑左右子树,只存在与d-1与d-2两种情况
对于节点数n,可以枚举左右子树分别有多少,有i和n-i-1两种情况
那么转移的方程用到了乘法原理
dp[i][d]= dp[i - j - 1][d - 1] * dp[j][d - 1] + dp[i - j - 1][d - 1] * dp[j][d - 2] + dp[i - j - 1][d - 2] * dp[j][d - 1]
然后注意一些细节,见代码
- #include<bits/stdc++.h>
- #define add(a, b) a = (a + b) % MOD
- #define REP(i, a, b) for(register int i = (a); i < (b); i++)
- #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
- using namespace std;
- typedef long long ll;
- const int MAXN = 2e3 + ;
- const int MAXM = ;
- const int MOD = ;
- ll dp[MAXN][MAXM + ];
- int n;
- int main()
- {
- scanf("%d", &n);
- dp[][] = dp[][] = ; //注意这个初始化,特别注意空的节点
- _for(i, , n)
- _for(d, , MAXM) //深度最大也就十几左右
- REP(j, , i) //最少0个,最多i-1个
- {
- add(dp[i][d], dp[i - j - ][d - ] * dp[j][d - ] % MOD);
- add(dp[i][d], dp[i - j - ][d - ] * dp[j][d - ] % MOD);
- add(dp[i][d], dp[i - j - ][d - ] * dp[j][d - ] % MOD);
- }
- ll ans = ;
- _for(d, , MAXM)
- add(ans, dp[n][d]);
- printf("%lld\n", ans);
- return ;
- }
输入
- 第一行两个数n,m(n<=20,m<=100)。
- 接下来m行,每行一个数ai,表示第ai道题目可能会有i这个分数的档次。
输出
- 一个数表示最多逆序对个数。
输入样例
- 5 7
- 1
- 2
- 3
- 4
- 1
- 2
- 5
输出样例
- 4
- n<=20
反应到状压dp
一般来说,逆序对是按照位置的顺序来求的
但是这道题要逆向思维,按照大小来求
因为题目输入的权值是递增的
所以只要判断在当前位置的后面有多少位置即可
但是这里要注意一点,我一开始用填表法去做,会WA
因为这里状态转移的时候涉及状态本身中1的个数,而有些状态是不合法的。
以前很多题可以用填表法是因为更新状态的时候用到的是状态中的某个位置,然后由位置导出权值,这样即使位置不合法,
导出权值的时候也会不合法而不会导致错解。但这道题就是用到状态本身,使得不合法的状态会导致错解
填表法就会把这些状态算进来。或者加个判断,判断之前的状态要是合法的,但是这显然没有刷表法方便
如果用到刷表法的话,就要注意初始化,起始状态初始化为0,其他为-1,表示不合法
然后转移的时候要判断当前状态合不合法
- #include<bits/stdc++.h>
- #define REP(i, a, b) for(register int i = (a); i < (b); i++)
- #define _for(i, a, b) for(register int i = (a); i <= (b); i++)
- using namespace std;
- int dp[( << ) + ], n, m;
- int main()
- {
- memset(dp, -, sizeof(dp));
- dp[] = ;
- scanf("%d%d", &n, &m);
- _for(k, , m)
- {
- int x; scanf("%d", &x); x--;
- REP(S, , << n)
- if(dp[S] >= && !(S & ( << x)))
- {
- int sum = ;
- REP(j, x + , n)
- if(S & ( << j))
- sum++;
- dp[S | ( << x)] = max(dp[S | ( << x)], dp[S] + sum);
- }
- }
- printf("%d\n", dp[( << n) - ]);
- return ;
- }
NOIP2018提高组金牌训练营——动态规划专题的更多相关文章
- NOIP2018提高组金牌训练营——搜索专题
NOIP2018提高组金牌训练营——搜索专题 1416 两点 福克斯在玩一款手机解迷游戏,这个游戏叫做”两点”.基础级别的时候是在一个n×m单元上玩的.像这样: 每一个单元有包含一个有色点.我们将用不 ...
- NOIP2018提高组金牌训练营——字符串专题
NOIP2018提高组金牌训练营——字符串专题 1154 回文串划分 有一个字符串S,求S最少可以被划分为多少个回文串. 例如:abbaabaa,有多种划分方式. a|bb|aabaa - 3 个 ...
- NOIP2018提高组金牌训练营——数论专题
地址 https://www.51nod.com/live/liveDescription.html#!liveId=23 1187 寻找分数 给出 a,b,c,d, 找一个分数p/q,使得a/b & ...
- [NOIp2018提高组]旅行
[NOIp2018提高组]旅行: 题目大意: 一个\(n(n\le5000)\)个点,\(m(m\le n)\)条边的连通图.可以从任意一个点出发,前往任意一个相邻的未访问的结点,或沿着第一次来这个点 ...
- [NOIp2018提高组]赛道修建
[NOIp2018提高组]赛道修建 题目大意: 给你一棵\(n(n\le5\times10^4)\)个结点的树,从中找出\(m\)个没有公共边的路径,使得第\(m\)长的路径最长.问第\(m\)长的路 ...
- [NOIp2018提高组]货币系统
[NOIp2018提高组]货币系统 题目大意: 有\(n(n\le100)\)种不同的货币,每种货币的面额为\([1,25000]\)之间的一个整数.若两种货币系统能够组合出来的数是相同的的,那我们就 ...
- [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路
[NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...
- NOIP2018提高组省一冲奖班模测训练(六)
NOIP2018提高组省一冲奖班模测训练(六) https://www.51nod.com/Contest/ContestDescription.html#!#contestId=80 20分钟AC掉 ...
- NOIP2018提高组省一冲奖班模测训练(五)
NOIP2018提高组省一冲奖班模测训练(五) http://www.51nod.com/Contest/ContestDescription.html#!#contestId=79 今天有点浪…… ...
随机推荐
- [GraphQL] Apollo React Mutation Component
In this lesson I refactor a React component that utilizes a higher-order component for mutations to ...
- sikuli类、函数使用参考java doc
sikuli类.函数使用可以参考java dochttp://doc.sikuli.org/javadoc/ http://stackoverflow.com/questions/9568612/s ...
- Leetcode:remove_element
一. 题目 给定一个数组和一个值.删除当中和给定值相等的元素.返回得到的新数组长度 二. 分析 刚開始我以为仅仅须要返回最后的数组长度即可了呢! 后来WA了一次才知道还得把心数组构造好 ...
- 2016.04.19,英语,《Vocabulary Builder》Unit 16
top, comes from topos, the Greek word for 'place'. ectopic: [ek'tɑːpɪk] adj. [医]异位的,异常的 topical: ['t ...
- SQL SERVER读书笔记:nolock
让查询语句不去申请共享锁,从而消除死锁,效果立竿见影. 缺点: 1.脏读 2.只能解决共享锁(S锁)参与的问题 3.需要修改语句本身才能使用
- Windows下Vim主题变更
默认的好丑! 主题位置. 修改配置文件. 添加主题设置. 新的主题,很高端大气. set fileencodings=utf8,ucs-bom,cp936,big set fileencoding=u ...
- H3C路由器查看序列号信息
H3C MSR系列的路由器,查看本机的MAC地址.序列号信息和生产日期信息等可以使用dis device manuinfo 命令查看,以下是执行结果: slot 0 DEVICE_NAME ...
- [牛客网练习赛 45 F] Magic Slab 解题报告 (最大权闭合子图)
interlinkage: https://ac.nowcoder.com/acm/contest/847/F description: solution: 最大权闭合子图; 每个单元格看成一个正权点 ...
- Blender Python UV 学习
Blender Python UV 学习 1. bmesh面转换 bm = bmesh.from_edit_mesh(bpy.context.edit_object.data) bm.faces.en ...
- Android线程间异步通信机制源码分析
本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础 ...