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

平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树。 现在问题来了,给定AVL树的节点个数n,求有多少种形态的AVL树恰好有n个节点。
 

输入

一行,包含一个整数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 ;
}
 
 
lyk最近计划按顺序做n道题目,每道题目都分为很多分数档次,lyk觉得这些题太简单了,于是它想到了一个好玩的游戏。

lyk决定将每道题目做出其中的某个分数,使得这n道题目的逆序对个数最多。
为了方便,假设共有m个分数档次,并且会给m个分数档次分配一个题目编号,表示该题目会出现这个分数档次。
题目保证每道题都存在至少一个分数档次。(例如样例中5道题目的分数分别是5,6,3,4,7,共有4个逆序对)

输入

第一行两个数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提高组金牌训练营——动态规划专题的更多相关文章

  1. NOIP2018提高组金牌训练营——搜索专题

    NOIP2018提高组金牌训练营——搜索专题 1416 两点 福克斯在玩一款手机解迷游戏,这个游戏叫做”两点”.基础级别的时候是在一个n×m单元上玩的.像这样: 每一个单元有包含一个有色点.我们将用不 ...

  2. NOIP2018提高组金牌训练营——字符串专题

    NOIP2018提高组金牌训练营——字符串专题 1154 回文串划分 有一个字符串S,求S最少可以被划分为多少个回文串. 例如:abbaabaa,有多种划分方式.   a|bb|aabaa - 3 个 ...

  3. NOIP2018提高组金牌训练营——数论专题

    地址 https://www.51nod.com/live/liveDescription.html#!liveId=23 1187 寻找分数 给出 a,b,c,d, 找一个分数p/q,使得a/b & ...

  4. [NOIp2018提高组]旅行

    [NOIp2018提高组]旅行: 题目大意: 一个\(n(n\le5000)\)个点,\(m(m\le n)\)条边的连通图.可以从任意一个点出发,前往任意一个相邻的未访问的结点,或沿着第一次来这个点 ...

  5. [NOIp2018提高组]赛道修建

    [NOIp2018提高组]赛道修建 题目大意: 给你一棵\(n(n\le5\times10^4)\)个结点的树,从中找出\(m\)个没有公共边的路径,使得第\(m\)长的路径最长.问第\(m\)长的路 ...

  6. [NOIp2018提高组]货币系统

    [NOIp2018提高组]货币系统 题目大意: 有\(n(n\le100)\)种不同的货币,每种货币的面额为\([1,25000]\)之间的一个整数.若两种货币系统能够组合出来的数是相同的的,那我们就 ...

  7. [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路

    [NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路 题目大意: 对于长度为\(n(n\le10^5)\)的非负数列\(A\),每次可以选取一个区间\(-1\).问将数列清零至少需要 ...

  8. NOIP2018提高组省一冲奖班模测训练(六)

    NOIP2018提高组省一冲奖班模测训练(六) https://www.51nod.com/Contest/ContestDescription.html#!#contestId=80 20分钟AC掉 ...

  9. NOIP2018提高组省一冲奖班模测训练(五)

    NOIP2018提高组省一冲奖班模测训练(五) http://www.51nod.com/Contest/ContestDescription.html#!#contestId=79 今天有点浪…… ...

随机推荐

  1. MySQL优化之——为用户开通mysql权限

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46627263 为用户开通mysql权限: grant all privileges ...

  2. 项目PMO工作

     算起来.这是第一次以项目PMO人员的身份參与项目,尽管非常可惜没有从头參与,也没有參与到项目结束,仅仅有短短的两个月.但对项目PMO也可略窥一斑.如今就当个流水账写一写吧. 进项目组的时候,是中 ...

  3. AdaBoostClassifier实战

    AdaBoostClassifier实战 部分内容摘自:http://blog.csdn.net/sun_shengyun/article/details/54289955 这里我们用一个具体的例子来 ...

  4. Java-Maven:POM百科

    ylbtech-Java-Maven:POM百科 Maven是以项目为中心的设计.POM(project object model)是Maven对一个单一项目的描述.没有POM的话,Maven是毫无用 ...

  5. if,elif,else的关系 input print int的用法

    qian=input("找劳保网是什么网站?:")if qian=="zhaolaobaowang.com": print("正确")els ...

  6. 跨域解决方案之JSONP,通过借助调用百度搜索的API了解跨域案例

    跨域解决方案之JSONP 同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web ...

  7. NOIP2012D2T1 同余方程

    [NOIP2012T4]同余方程 noip2012-tg 描述 求关于 x的同余方程 ax ≡ 1(mod b) 的最小正整数解. 输入格式 输入文件 mod.in 输入只有一行,包含两个正整数a,b ...

  8. 由于找不到 opencv_world320.dll,无法继续执行代码

    首先找到自己软件安装(解压)的路径openCV (安装(解压)目录\opencv\build\x64\vc14\bin) 我的安装(解压)目录是:F:\OpenCV\Three320\opencv\b ...

  9. 第4章 部署模式 Three-Tiered Distribution(三级分布)

    影响因素 Tiered Distribution 中讨论的影响因素也适用于此模式.有关这些通用影响因素的讨论,请参阅"Tiered Distribution".下列影响因素仅适用于 ...

  10. Android 拍照图片选取与图片剪裁

    最近从以前的项目中扒下来一个常用的模块,在这里有必要记录一下的,就是android上获取图片以及裁剪图片,怎么样?这个功能是不是很常用啊,你随便打开一个App,只要它有注册功能都会有设置人物头像的功能 ...