楼梯有 nnn 阶,上楼可以一步上一阶,也可以一步上二阶。
但你不能连续三步都走两阶,计算走到第nnn阶共有多少种不同的走法。
一行,一个数字,表示nnn。
输出走楼梯的方式总数。
6
12
对于100100100%的数据,保证n≤50n≤50n≤50。
需要遍历每一种情况,很容易想到DP
如果没有限制“不能连续三步都走两阶”,本题就是简单的兔子数列
dp[0] = 1;//简单的初始化条件,台阶数为0,只有一种可能for (int i = 1; i <= max_step; i++)dp[i] = dp[i - 1] + dp[i - 2];
多了限制,自然就少了可能
那么尝试用排除法
需要排除走666、888、101010、141414、.........,显然需要排除的情况太多了
所以我们采用正难则反的思路,正面求解
对于每一步,我们有三种选择(只有三种情况,不难证明):111、222、444
但是需要考虑限制,所以有以下几种情况
(1)当前走了111步,到达此处的方式不受限制
(2)当前走了222步,所以我们只能通过走111步的方式到达此处
(3)当前走了444步,所以我们只能通过走111步的方式到达此处
很简单,于是我们根据这个思路写出代码
int dp[max_step + 1] = { 0 };//存储数据含义:到达当前位置之后的可能数
bool disable[max_step + 1][3] = { false };//限制标记
int step[3] = { 1,2,4 };dp[0] = 1;//简单的初始化条件,台阶数为0,只有一种可能for (int i = 1; i <= max_step; i++) {for (int j = 0; j < 3; j++) {if (!disable[i - step[j]][j]) {dp[i] += dp[i - step[j]];if (j != 0) disable[i][1] = disable[i][2] = true;//只能通过走1步的方式到达}}
}
结束了?当然没有,这个思路是有一点瑕疵的
假如当前有444级台阶,有几种方法?
很快你就会回答有555种,但是计算机会回答有444种
那么是哪一种可能性被漏掉了呢?
1 1 1 1
2 1 1
1 2 1
1 1 2
2 2
是第三种可能消失了
因为我们被禁止跳222级台阶到达dp[2]
,但是这不是应该被禁止的吗?
我们要禁止的是跳222级、跳444级连续选择
但是上面的方法会导致跳222级之后跳111级的可能也被去除了,所以我们修改代码,把跳1,2,41, 2, 41,2,4级的情况分开存储
int dp[max_n + 1][3];//存储的数据含义:以方式j到达当前位置之后的可能数
int step[3] = { 1,2,4 };dp[0][0] = dp[0][1] = dp[0][2] = 1;for (int i = 1; i <= max_step; i++) {for (int j = 0; j < 3; j++) {dp[i][0] += dp[i - step[j]][j];if (j == 1) dp[i][j] += dp[i - step[0]][0];else if (j == 2) dp[i][j] += dp[i - step[0]][0];}
}
最后,AC代码如下
#include
#include
using namespace std;
const int max_n = 50;
const int bias = 4;//加上偏置量,防止数组越界long long dp[max_n + 1 + bias][3];
int step[3] = { 1,2,4 };int main() {int n;cin >> n;dp[0 + bias][0] = dp[0 + bias][1] = dp[0 + bias][2] = 1;for (int i = 1 + bias; i <= n + bias; i++) {for (int j = 0; j < 3; j++) {dp[i][0] += dp[i - step[j]][j];if (j == 0) {dp[i][1] += dp[i - step[j]][j];dp[i][2] += dp[i - step[j]][j];}}}cout << dp[n + bias][0];return 0;
}
你有nnn个任务,其中第iii个任务,在sis_isi开始,eie_iei时刻结束,如果做这个任务,你能获得wiw_iwi的收益。
但是你在一个时刻只能做一个任务,问选择哪些任务,能让你的收益尽量大。
注意:你在上一个任务结束后马上开始下一个任务是可以的。
第一行一个整数nnn。
接下来nnn行,每行三个整数sis_isi,eie_iei,wiw_iwi。
一个数,表示答案。
3
1 3 100
2 4 199
3 5 100
200
对于所有数据,保证1≤n≤103,1≤si 本题是一道非常规的、同时也是非常好的动态规划题目,具体的“非常规”体现在DP的思路上,接下来说明解题思路 题意抽象来说就是给了起止111~100010001000区间范围内的多条线段,每条线段有自己的权重,选择的线段不能重叠,问如何选使得得到的线段权重最大 很明显,这是一道动态规划问题,那么如何动态规划? 动态规划的关键在于如何从子问题推出更复杂问题的答案 首先我们尝试确定一个子问题的状态: (1)当前可以得到的最大权重 (2)当前的截止时间 (3)当前考虑的线段数量 先试一下根据(3)展开动态规划,也就是按照常规背包问题的思路 我们会发现我们无法从只考虑前 比如说有如下三条线段 只考虑前两条线段的时候我们可以得到的最大值是 但是我们如果选择第 所以我们换一个角度考虑,有关线段覆盖的问题,终止时间是很重要的 如果到终止时间 从这里我们可以看出最优子结构的存在 那么尝试一下动态规划,还是这样三条线段 考虑截止时间为 好像我们还是不能从截止时间为 所以说这道题是一道“非常规”的动态规划问题 我们不是在尝试用截止时间为 而是尝试用截止时间为 我们实现了在到达 然后去尝试所有起始时间是 最后,AC代码如下 有一条很长的数轴,一开始你在000的位置。接下来你要走nnn步,第iii步你可以往右走aia_iai或者bib_ibi。 问nnn步之后,000到mmm的每个位置,能不能走到? 第一行,两个整数nnn,mmm。 接下来nnn行,每行两个整数aia_iai,bib_ibi。 一行,一共m+1m+1m+1个数,每个数都是 对于所有数据,保证1≤n≤100,1≤m≤105,1≤ai,bi≤10001≤n≤100,1≤m≤105,1≤a_i,b_i≤10001≤n≤100,1≤m≤105,1≤ai,bi≤1000。 一定要看到是“往右走aia_iai或者bib_ibi“而不是”往右走aia_iai或者往左走bib_ibi“ 那么接下来讨论如何实现代码 题意还是有一点模糊的,问的不是你在 显然需要遍历每一种情况,采用动态规划来实现 动态规划最重要的自然是明确每一步需要做什么,也就是状态转移方程: 解释一下: 也就是说,只要你在第 最后,AC代码如下 输入nnn,输出nnn行nnn列的由 一行,一个整数nnn。 nnn行,为满足题目要求的正方形。注意不要有行末空格。 对于100100100%的数据,保证2≤n≤1002≤n≤1002≤n≤100 虽然本题数据范围不大,可以直接实现数组存储,然后输出 但这里仍然采用无存储的方式实现 二维图形输出,自然采用二重循环实现 关键在于如何调整输出 这里通过两条对角线来实现调整 每次输出前反转两条对角线之间要输出的符号,我们具体模拟一下来说明 初始化输出模式 然后我们来到第一行,反转之后的输出模式 然后我们来到第二行,反转之后的输出模式 然后我们来到第三行,反转之后的输出模式 … 是不是很好理解?但是没有结束,我们需要特殊处理 因为当前每一次循环执行的动作是简单的:反转,然后输出 但是如果这样的话,前半段输出是对的,后半段就会出现错误,如下 所以我们稍微调整一下: (1)前半段:反转,然后输出 (2)后半段:输出,然后反转 最后,AC代码如下 小缘开了一家公司,生意很好,每天都会收到很多订单,自动交易系统会自动给这些订单生成没有重复的订单编号。但是有一天,系统出现了未知的错误,导致当天的订单编号可能有重复的,这可把小缘急坏了。你可以帮助小缘按照规则给这些订单重新编号吗? 按照时间先后顺序给出 NNN 个正整数作为原订单编号,你需要按照规则依次赋予这些订单新的编号,对于任意一个订单,要找到大于等于其原订单编号且未被使用过的(没有被之前的订单作为新的订单编号)的最小整数,作为它的新订单编号。 例如: 原订单编号依次为111 222 333 111,则新订单编号应该为111 222 333 444 (前333个订单的原订单编号都没有使用过,所以用其原订单编号即可,对于第四个订单,原订单编号为111,而111, 222, 333都已经被使用过,所以新订单编号为444)。 第一行输入一个整数 NNN (1≤N≤5×1051≤N≤5×10^51≤N≤5×105)。 第二行输入 NNN 个数 aia_iai (1≤ai≤1091≤a_i≤10^91≤ai≤109) 作为原订单编号。 输出一行,包含 NNN 个整数为新的订单编号。 本题考察对STL的掌握 采用 主要是利用 代码如下 有nnn个同学正在排队打饭,第iii个同学排在从前往后第iii个位置。但是这天食堂内只有一个食堂阿姨,为了使同学们都能尽快的吃上饭,每一个同学在打完一份饭之后就会排在队伍的末尾先吃着打到的饭,我们知道第iii个同学的饭量为aia_iai,也就是说第iii个同学要吃aia_iai份饭才能吃饱,当一位同学吃饱后,他就会立刻离开食堂,不会排在队伍的末尾。食堂阿姨想知道,在打完k份饭之后,队伍的样子是怎样的,但是食堂阿姨数学不太好,想让你帮忙想想办法。 第一行给出两个整数nnn,kkk。 第二行给出nnn个整数a1a_1a1,a2a_2a2,…ana_nan。 如果食堂阿姨打饭数少于kkk,请输出 否则按照队伍顺序输出每一个同学的编号。 数据保证1≤n≤105,0≤k≤1014,1≤ai≤1091≤n≤105, 0≤k≤1014, 1≤a_i≤10^91≤n≤105,0≤k≤1014,1≤ai≤109。 先采用二分搜索找出需要多少轮才能分完所有的饭,如果找不到输出 反之先进行 代码如下 NNN 个好朋友在codeforcescodeforcescodeforces上参加一场包含 MMM 个题目的比赛, 比赛期间codeforcescodeforcescodeforces网站一共有 kkk 次提交。 已知每个题目的分数, 但是由于他们只能查到在比赛期间codeforcescodeforcescodeforces总共的提交记录(其他用户提交的其他题目记录也包含在内, 即存在不属于该场比赛的题目), 所以想请你编写一个程序算出他们每个人的分数。 第一行三个整数 NNN, MMM, KKK 分别表示好朋友的个数, 题目的个数, 和提交的总次数(其中0 接下来 NNN 行 第 iii 行输入为第 iii 个人的ididid, 接下来 MMM 行 第 jjj 行输入为第 jjj 个题目的名称和分数, 接下来 KKK 行 第 kkk 行输入为第 kkk 次提交的提交者iii, 题目名称和结果(“WA” 或 “AC”, 如果"AC"代表通过这个题目, 提交者获得对应分数)。 注: 题目名称和id均为仅包含英文字母和数字的字符串, 题目分数为小于等于 1e61e61e6 的正整数. 每一行的多个输入之间用空格隔开。 所有输入的字符串长度 lengthlengthlength 满足 0 所有用户id和题目名称不存在重名, 用户AC了某个题之后之后不会再重复提交该题, 好朋友们只会提交属于比赛的题目。 输出 NNN 行, 第 iii 行输出第 iii 个人的名字和对应分数 (名字和分数用空格隔开)。 bezabezabeza 过了 metebroncametebroncametebronca和geometrygeometrygeometry 拿到 300300300 分。 GabrielPessosGabrielPessosGabrielPessos 没有过题, 所以是 000 分。 还有一些其他选手提交的其他题目忽略不计。 一道考察字符串的题目 对于提交者,用 对于题目,用 然后判断是否 AC代码如下 德州扑克是目前世界上最流行的扑克游戏,全世界有众多相关的比赛,例如是 WSOP,WPT,EPT等,也让这款游戏的玩法变得层出不穷,丰富多变。 不要被简单的游戏规则而误导,复杂多变的比赛状况,让这款游戏在高水平的竞技中会变得非常复杂,这也让人们为德州扑克给出了这样一句评价 ”用一刻就能学会,但要用一生才能掌握” 。 现在我们并不在乎游戏规则是什么,因为 Alice 是一个德州扑克高手,他对于德州扑克的规则烂熟于心,不过他每次都记不得牌型的大小关系,他知道你是一个编程高手,所以他想让你帮他写一个程序:输入五张牌的大小和花色,输出这五张牌能组成的最大牌型.你能帮帮他吗? 为了降低你的编程难度,我们规定: 下面给出各牌型,(从大到小) 输入两行,每行五个数字,第一行的第 iii 个字符表示第 iii 张扑克的点数, 第二行的第 iii 个数字表示第 iii 张扑克花色。(保证输入的牌的点数是非递减的,且所有输入均合法)。 点数和对应输入的数字: 花色和对应输入的数字: 输出这五张牌能组成的最大牌型。 这里将要说明的代码的适用范围要比题目所给出的更广 因为我题读错了QAQ 改动了以下几点: (1)输入两行,以换行符结尾 (2)第一行输入若干个扑克牌点数,分别是222~101010和JJJ,QQQ,KKK,AAA 首先这是一道模拟问题 我们可以注意到,不同combocombocombo之间是有包含关系的,而且所有combocombocombo由五种条件组合而成: (1)顺子:五张连续 (2)同花:五张同花 (3)222张、333张、444张点数相同 所以我们的判定自然也有顺序,这样就可以简化问题 输入点数之后我们就可以寻找(1)和(3)了 之后判断是否有顺子、葫芦和四条 然后输入点数,寻找(2) 当且仅当顺子和同花已经找到的情况下,我们继续寻找最大的两种combocombocombo 最后输出最大的combocombocombo即可解题思路
i - 1
个物品的情况推导出前i
个物品的情况1 2 10
1 3 20
2 4 100
20
,也就是选择第2
条线段2
条线段,我们就不能得到选择1
、3
线段的最优解i
之前的最大值是已知的,那么我们就只需要考虑i
之后的最大值了1 2 10
1 3 20
2 4 100
3
时的最大值,是20
3
时的最大值推出截止时间为4
时的最大值i - 1
时的情况推导出截止时间为i
时的情况i
时的情况去更新之后所有情况的最大值for (int i = 1; i < max_se; i++) {dp[i + 1] = max(dp[i + 1], dp[i]);for (int j = 1; j <= n; j++) {if (i == tasks[j].s) {dp[tasks[j].e] = max(dp[tasks[j].e], dp[i] + tasks[j].w);}}
}
dp[i]
之前,尝试过了所有可能的情况,保证了dp[i]
是最优解i
的任务,更新之后的所有元素#include
[Daimayuan]走路(C++,DP)
输入格式
输出格式
0
或1
表示能否走到,数字之间不用空格隔开。输入样例
3 10
1 2
2 6
3 3
输出样例
00000011001
数据规模
解题思路:
如果不是像我一样把题看错了的话应该知道这就是一道简单的动态规划问题n
步之内能够到达的所有地方,而是你在第n
步能够到达的所有地方dp[i][j] = dp[i - 1][j - step[i][0]] || dp[i - 1][j - step[i][1]]
dp[i]
代表你当前的是第i
步dp[i][j]
代表你当前的位置为j
step[i][0]
和step[i][1]
代表你可以向右走几步i - 1
步时能够到达j - step[i][0]
或者j - step[i][1]
,你就能到达dp[i][j]
#include
[Daimayuan]特殊的正方形(C++)
+
和.
组成的正方形,其中最外面一圈全是+
,第二圈全是.
,…,对于第iii圈,如果iii是奇数,那么全是+
,否则全是.
。输入格式
输出格式
样例输入
10
样例输出
++++++++++
+........+
+.++++++.+
+.+....+.+
+.+.++.+.+
+.+.++.+.+
+.+....+.+
+.++++++.+
+........+
++++++++++
数据范围
解题思路:
.
还是+
..........
++++++++++
+........+
+.++++++.+
++++++++++
+........+
+.++++++.+
+.+....+.+
+.+.++.+.+
+.+....+.+
+.++++++.+
+........+
++++++++++
..........
#include
[Daimayuan]订单编号(C++,STL)
输入格式
输出格式
样例输入1
6
2 3 4 1 1 1
样例输出1
2 3 4 1 5 6
样例输入2
3
1000000000 1000000000 1000000000
样例输出2
1000000000 1000000001 1000000002
样例输入3
6
4 5 1 2 1 1
样例输出3
4 5 1 2 3 6
解题思路:
set
+pair
维护未使用序号的区间来解决本题set
的lower_bound
方法:传入一个val
,返回集合中大于等于val
的最小值;如果是pair
数据类型,默认先比较first
再比较second
#include
[OJ]饿饿 饭饭(C++,二分)
输入格式
输出格式
-1
。样例输入1
3 3
1 2 1
样例输出1
2
样例输入2
4 10
3 3 2 1
样例输出2
-1
样例输入3
7 10
1 3 3 1 2 3 1
样例输出3
6 2 3
数据规模
解题思路:
-1
ret - 1
轮,然后模拟最后一轮,最后输出即可#include
[OJ]简单分数统计(C++,字符串)
输入格式
输出格式
样例输入
2 2 4
GabrielPessoa
beza
metebronca 100
geometry 200
beza metebronca AC
ffern numbertheory AC
GabrielPessoa geometry WA
beza geometry AC
样例输出
GabrielPessoa 0
beza 300
样例解释
解题思路
map
转换id
为数组索引号map
转换名字为分数AC
累加求和即可#include
[OJ]Alice的德州扑克(C++,字符串)
输入格式
输出格式
样例输入1
10 11 12 13 14
1 1 1 1 1
样例输出1
ROYAL FLUSH
样例输入2
10 11 12 13 14
1 2 1 3 4
样例输出2
STRAIGHT
样例输入3
6 6 6 7 7
1 2 3 1 3
样例输出3
FULL HOUSE
样例输入4
3 3 6 6 9
1 2 1 2 1
样例输出4
FOLD
解题思路
所以只是想要解决原题问题的可以划过去了//Alice的德州扑克
#include