[TOC]

动态规划

P8784 蓝桥杯 2022 省 B - 积木画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const int mod = 1000000007;

int f[6] = { 0,1,2,5 };

signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

int n;
cin >> n;

for (int i = 4; i <= n; i++) {
f[i] = (2 * f[i-1] % mod + f[i-3] % mod) % mod;
}

cout << f[n];

return 0;
}

P8786 蓝桥杯 2022 省 B - 李白打酒加强版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const int mod = 1000000007;

int jiu[201][101][101];

signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

int n, m;
cin >> n >> m;

jiu[0][0][2] = 1;
//i 位置
//j 花
//k 酒
for (int i = 0; i < n + m; i++) {
for (int j = 0; j < m; j++) {
for (int k = 0; k <= m; k++) {
if (jiu[i][j][k]) {
if (k > 0) jiu[i + 1][j + 1][k - 1] = (jiu[i + 1][j + 1][k - 1] + jiu[i][j][k]) % mod;
if (k <= m/2) jiu[i + 1][j][k * 2] = (jiu[i + 1][j][k * 2] + jiu[i][j][k]) % mod;
}
}
}
}

cout << jiu[n + m][m][0];

return 0;
}

P2758 编辑距离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
int n, m;
int ans;
//dp[i][j]

//A的前i位转换为 B前j位的最小步骤
int dp[2001][2001];
/*
Ⅰ:删除一个字符;
Ⅱ:插入一个字符;
Ⅲ:将一个字符改为另一个字符。
*/
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

string str1, str2;
cin >> str1 >> str2;
n = str1.size();
m = str2.size();
for (int i = 1; i <= n; i++) {
dp[i][0] = i;
}
for (int i = 1; i <= m; i++) {
dp[0][i] = i;
}

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (str1[i - 1] == str2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
continue;
}

//分别对应i情况: Ⅰ Ⅱ Ⅲ
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
}

cout << dp[n][m];

return 0;
}

P1077 NOIP2012 普及组 摆花

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int dp[101][101];
int n, m;
int a[101];

signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
//m盆
//n种花
//第i种不能超ai盆
//同一种放一起,标号从小到大排
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}

for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
for (int num = 0; num <= min(j,a[i]); num++) {
//状态方程
//i种j盆的方法数 = 自身 + i-1种j-a_i选择盆的方法数
dp[i][j] = (dp[i][j] + dp[i - 1][j - num])%1000007;
}
}
}

cout << dp[n][m];
return 0;
}

P4933 大师 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define mod 998244353

int n;
int h[1001];
int dp[1001][40001];

signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

cin >> n;
for (int i = 1; i <= n; i++) {
cin >> h[i];
}

int ans = 0;
for (int i = 1; i <= n; i++) {
ans++;//每个数自身也是一个答案
for (int j = i - 1; j; j--) {
dp[i][h[i] - h[j] + 20000] += dp[j][h[i] - h[j] + 20000] + 1;
dp[i][h[i] - h[j] + 20000] %= mod;
ans += dp[j][h[i] - h[j] + 20000] + 1;
ans %= mod;
}
}


cout << ans;

return 0;
}

[P1091 NOIP2004 提高组 合唱队形

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

cin >> n;
for (int i = 0; i < n; i++) {
cin >> h[i];
}

for (int i = 0; i < n; i++) {
dp[i][0] = 1;
for (int j = 0; j < i; j++) {
if (h[j] < h[i]) {
dp[i][0] = max(dp[i][0], dp[j][0] + 1);
}
}
}

for (int i = 0; i < n; i++) {
dp[i][1] = 1;
for (int j = 0; j < i; j++) {
if (h[j] > h[i]) {
dp[i][1] = max(dp[i][1], max(dp[j][0], dp[j][1]) + 1);
}
}
}

int ans = 0;
for (int i = 0; i < n; i++) {
ans = max(ans, max(dp[i][0], dp[i][1]));
}

cout << n - ans;

return 0;
}

前序后序,确定中序数量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//子结点为1的节点数目为n
//2^n即为答案

string pre, post;
cin >> pre >> post;

int b = 0;
for (int i = 0; i < pre.size() - 1; i++) {
for (int j = 1; j < post.size(); j++) {
if (pre[i] == post[j] && pre[i + 1] == post[j - 1])
b++;
}
}

cout << (1 << b);

堆栈

小顶堆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const int MAXN = 1314;
const int MINH = -1314;
int minS[MAXN], _size;

void Creat() {
_size = 0;
minS[0] = MINH;//设置岗哨
}

void Insert(int x) {
int i;
//岗哨的作用体现,岗哨是比插入数据都小的,不会导致越界
for (i = ++_size; minS[i / 2] > x; i /= 2)
minS[i] = minS[i / 2];
minS[i] = x;
}



int main() {
int n, m;
//一个有n个数据的堆,m次查找
cin >> n >> m;
Creat();
int x;
for (int i = 0; i < n; i++) {
cin >> x;
Insert(x);
}

//m次查找,根据查找所给下标,返回其到根的路径
for (int i = 0; i < m; i++) {
cin >> x;
cout << minS[x];
while (x > 1) {
x /= 2;
cout << " " << minS[x];
}
cout << endl;
}

return 0;
}