当前位置: 首页 > news >正文

衡水精品网站建设谷歌排名推广公司

衡水精品网站建设,谷歌排名推广公司,哈尔滨关键词优化排行,北京做网站电话的公司title: 线性动态规划 date: 2023-05-12 08:49:10 categories: Algorithm动态规划 tags:动态规划 编辑距离 题目描述 设 A A A 和 B B B 是两个字符串。我们要用最少的字符操作次数,将字符串 A A A 转换为字符串 B B B。这里所说的字符操作共有三种&#xff1…

title: 线性动态规划
date: 2023-05-12 08:49:10
categories:

  • Algorithm
  • 动态规划
    tags:
  • 动态规划

编辑距离

题目描述

A A A B B B 是两个字符串。我们要用最少的字符操作次数,将字符串 A A A 转换为字符串 B B B。这里所说的字符操作共有三种:

  1. 删除一个字符;
  2. 插入一个字符;
  3. 将一个字符改为另一个字符。

A , B A, B A,B 均只包含小写字母。

输入格式

第一行为字符串 A A A;第二行为字符串 B B B;字符串 A , B A, B A,B 的长度均小于 2000 2000 2000

输出格式

只有一个正整数,为最少字符操作次数。

样例 #1

样例输入 #1

sfdqxbw
gfdgw

样例输出 #1

4

提示

对于 100 % 100 \% 100% 的数据, 1 ≤ ∣ A ∣ , ∣ B ∣ ≤ 2000 1 \le |A|, |B| \le 2000 1A,B2000

思路

状态表示:f[i][j]表示将A的1~i变成B的1~j的操作次数的最小值

状态计算:三种操作方式如下:

  • 删除:将A[i]删除后应该与B[1~j]相同,说明A[1~(i-1)]==B[1~j]

    • 方程为:f[i-1][j]+1
  • 插入:在A[i]之后插入后与B[1~j]相同,则说明A[1~i]==B[1~j-1]

    • 方程为:f[i][j-1]+1
  • 替换:将A[i]替换后,A[1~i]==B[1~j]分两种情况:

    • 第一种是A[i]==B[j]已经相等了不需要替换,f[i-1][j-1]
    • 第二种是不想等,需要替换一次,f[i-1][j-1]+1

状态转移方程为上述三个取min

初始化的时候需要将:

  • f[i][0]=i表示删除i个字符与B相等
  • f[0][i]=i表示添加i个字符与B相等

或者这样考虑:

f[i][j]表示将A的1~i变成B的1~j的操作次数的最小值

  • 如果A[i]==B[j],则f[i][j]=f[i-1][j-1],

  • 如果A[i]!=B[j], 使用三种操作,取最小值

    • 修改:将a[i]改为b[i], f[i-1][j-1]+1
    • 插入:在a[i]后面插入b[i],f[i][j-1]+1
    • 删除:将a[i]删除,f[i-1][j]+1

代码

#include <bits/stdc++.h>#define int long long
using namespace std;
const int N = 2010;
int f[N][N];//将A 1-i变成 B 1-j的最小操作次数
string a, b;signed main() {
#ifndef ONLINE_JUDGEfreopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#endifcin >> a >> b;int n = a.size(), m = b.size();a = " " + a, b = " " + b;for (int i = 1; i <= n; i++) f[i][0] = i;for (int i = 1; i <= m; i++) f[0][i] = i;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (a[i] == b[j]) f[i][j] = f[i - 1][j - 1];else f[i][j]= min(f[i-1][j-1], min(f[i-1][j],f[i][j-1]))+1;}}cout << f[n][m];return 0;
}

899. 编辑距离 - AcWing

给定 n n n 个长度不超过 10 10 10 10 10 10 的字符串以及 m m m次询问,每次询问给出一个字符串和一个操作次数上限。

对于每次询问,请你求出给定的 n n n 个字符串中有多少个字符串可以在上限操作次数内经过操作变成询问给出的字符串。

每个对字符串进行的单个字符的插入、删除或替换算作一次操作。

输入格式

第一行包含两个整数 n n n m m m

接下来 n n n 行,每行包含一个字符串,表示给定的字符串。

再接下来 m m m 行,每行包含一个字符串和一个整数,表示一次询问。

字符串中只包含小写字母,且长度均不超过 10 10 10 10 10 10

输出格式

输出共 m m m 行,每行输出一个整数作为结果,表示一次询问中满足条件的字符串个数。

数据范围

1 ≤ n , m ≤ 1000 1 \le n, m \le 1000 1n,m1000 1 ≤ n , m ≤ 1000 1 \le n, m \le 1000 1n,m1000,

输入样例:

3 2
abc
acd
bcd
ab 1
acbd 2

输出样例:

1
3

思路

和上一题一样,将dp封装为一个函数即可。暴力统计是否能够转换。

代码

#include <bits/stdc++.h>#define int long long
using namespace std;
const int N = 20;
int f[N][N];int edit(string a, string b) {int n = a.size(), m = b.size();a = " " + a, b = " " + b;for (int i = 1; i <= n; i++) f[i][0] = i;for (int i = 1; i <= m; i++) f[0][i] = i;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {if (a[i] == b[j]) f[i][j] = f[i - 1][j - 1];else f[i][j] = min(f[i - 1][j - 1], min(f[i][j - 1], f[i - 1][j])) + 1;}}return f[n][m];
}signed main() {
#ifndef ONLINE_JUDGEfreopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#endifint n, m;cin >> n >> m;vector<string> a(n + 1);for (int i = 1; i <= n; i++) cin >> a[i];while (m--) {string s;int limit;cin >> s >> limit;int res = 0;for (int i = 1; i <= n; i++) {if (edit(a[i], s) <= limit) res++;}cout << res << endl;}return 0;
}

[NOIP1999 普及组] 导弹拦截

题目描述

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

输入格式

一行,若干个整数,中间由空格隔开。

输出格式

两行,每行一个整数,第一个数字表示这套系统最多能拦截多少导弹,第二个数字表示如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

样例 #1

样例输入 #1

389 207 155 300 299 170 158 65

样例输出 #1

6
2

提示

对于前 50 % 50\% 50% 数据(NOIP 原题数据),满足导弹的个数不超过 1 0 4 10^4 104 个。该部分数据总分共 100 100 100 分。可使用 O ( n 2 ) \mathcal O(n^2) O(n2) 做法通过。
对于后 50 % 50\% 50% 的数据,满足导弹的个数不超过 1 0 5 10^5 105 个。该部分数据总分也为 100 100 100 分。请使用 O ( n log ⁡ n ) \mathcal O(n\log n) O(nlogn) 做法通过。

对于全部数据,满足导弹的高度为正整数,且不超过 5 × 1 0 4 5\times 10^4 5×104

思路 (LIS+贪心 O ( n 2 ) O(n^2) O(n2))

第一问是LIS问题:

LIS 是 Longest ascending subsequence 的缩写

显然每套导弹拦截系统拦截导弹高度为步上升子序列,也就是最长不上升子序列,只需要求最长不上升子序列的长度就可以了,

状态的计算:

for (int j = 0; j < i; j++) if (q[j] >= q[i]) { // 不高于, 可以等于, 最长下降子序列(不完全下降,可以等于),严格来说是不上升子序列f[i] = max(f[i], f[j] + 1);

第二问是贪心问题:

贪心思路:

  • 较大的数的末尾元素比较小的数作为末尾元素的子序列更好,因为这样可以让这个子序列变得更长,如果放了一个较小的数,可能放的数就没有那么长了

贪心步骤:

  1. 开一个数组q[]记录所有下降子序列末尾元素

  2. 遍历每一个数,对于当前的这个数:

    1. q[]中所有的数都比这个数大,那么我们就扩大q[]的长度,并且把这个数放到q[]中刚开的地方
    2. q[]中存在比这个数小的数,那么我们就把当前的这个数覆盖到找到的比这个数小的最大的数
  3. 每次将一个较小的数换成一个较大的数作为末尾元素存储到q[], 随着q[]的长度扩大, 也就表示此时新增x比所有末尾元素都大时; q[]随下标增大元素值也越大, 因此q[]是单调上升的数组

这题的思路和AcWing 896. 最长上升子序列 II 一样,我们可以得出结论:

求解至少需要多少个下降子序列的数目

求解至多含有多少个上升子序列的数目是一个对偶问题

注:数组q[]是单调不减的!!!

代码

#include <iostream>
#include <algorithm>using namespace std;const int N = 1010;
int n;
int q[N];
int f[N], g[N];int main() {while (cin >> q[n]) n++;int res = 0;for (int i = 0; i < n; ++i) {f[i] = 1;for (int j = 0; j < i; j++) {if (q[j] >= q[i]) { // 不高于, 可以等于, 最长下降子序列f[i] = max(f[i], f[j] + 1);}}res = max(res, f[i]);}cout << res << endl;int cnt = 0;//当前子序列的个数for (int i = 0; i < n; i++) {int k = 0;//记录下从前往后找到的比当前的数q[i]小的最大的数while (k < cnt && g[k] < q[i]) k++;//  当前的序列结尾的数<=我们的数g[k] = q[i];if (k >= cnt) cnt++;//没有任何一个数是大于等于我们当前数的}cout << cnt << endl;return 0;
}

思路2( O ( n 2 ) O(n^2) O(n2))

可以把题目理解为:

  • 给定一个序列,求至少包含多少个下降子序列数目

等价于

  • 给定一个序列,求至多包含多少个上升子序列数目

也就是将题目转换为求解最长上升子序列的长度。

代码

#include <iostream>
#include <algorithm>
using namespace std;const int N = 1010;
int n;
int a[N], f[N];int main()
{// 第一问:问题是求最长下降子序列的长度while(cin >> a[n])n++;int res = 0;for (int i = 0; i < n; ++i) {f[i] = 1;for (int j = 0; j < i; ++j)if (a[i] <= a[j])f[i] = max(f[i], f[j] + 1);res = max(res, f[i]);}// 第二问:问题转化为求解最长上升子序列的长度int len = 0;for (int i = 0; i < n; ++i) {f[i] = 1;for (int j = 0; j < i; ++j) if (a[i] > a[j])f[i] = max(f[i], f[j] + 1);len = max(len, f[i]);}cout << res << endl;cout << len << endl;return 0;
}

思路3(二分+LIS O ( n l o g n ) O(nlogn) O(nlogn))

注意这里第一问需要倒着求最长上升子序列,这里的上升可以相等,因此使用的是upper_bound函数

代码

#include <bits/stdc++.h>#define int long long
using namespace std;const int N = 1e5 + 10;
int a[N];
int n = 1;signed main() {
#ifndef ONLINE_JUDGEfreopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#endifwhile (cin >> a[n])n++;n--;vector<int> f;f.push_back(a[n]);for (int i = n - 1; i >= 1; i--) {if (a[i] >= f.back()) f.push_back(a[i]);else {//找到第一个大于a[i]的数,换成a[i]*std::upper_bound(f.begin(), f.end(), a[i]) = a[i];}}cout << f.size() << endl;vector<int> g;g.push_back(a[1]);for (int i = 2; i <= n; i++) {if (a[i] > g.back())g.push_back(a[i]);else *std::lower_bound(g.begin(), g.end(), a[i]) = a[i];}cout << g.size() << endl;return 0;
}

187. 导弹防御系统

题目链接:https://www.acwing.com/problem/content/189/

为了对抗附近恶意国家的威胁, R R R 国更新了他们的导弹防御系统。

一套防御系统的导弹拦截高度要么一直 严格单调 上升要么一直 严格单调 下降。

例如,一套系统先后拦截了高度为 3 3 3 和高度为 4 4 4的两发导弹,那么接下来该系统就只能拦截高度大于 4 4 4 的导弹。

给定即将袭来的一系列导弹的高度,请你求出至少需要多少套防御系统,就可以将它们全部击落。

输入格式

输入包含多组测试用例。

对于每个测试用例,第一行包含整数 n n n,表示来袭导弹数量。

第二行包含 n n n不同的整数,表示每个导弹的高度。

当输入测试用例 n = 0 n=0 n=0 时,表示输入终止,且该用例无需处理。

输出格式

对于每个测试用例,输出一个占据一行的整数,表示所需的防御系统数量。

数据范围

1 ≤ n ≤ 50 1 \le n \le 50 1n50

输入样例:

5
3 5 2 4 1
0 

输出样例:

2

样例解释

对于给出样例,最少需要两套防御系统。

一套击落高度为 3 , 4 3,4 3,4 的导弹,另一套击落高度为 5 , 2 , 1 5,2,1 5,2,1 的导弹。

思路(DFS,迭代加深,剪枝,贪心)

up[k]down[k]记录第k套上升(下降)系统目前所拦截的最后一个导弹

dfs(u,v,t)意味着已有u个上升,v个下降,正在处理第t个数

代码

#include <bits/stdc++.h>#define int long long
using namespace std;int n;
const int N = 60;
int a[N];
int up[N], down[N];
int ans = 0;/*** @param u 当前第几个导弹* @param s 上* @param x 下*/
void dfs(int u, int s, int x) {if (s + x >= ans) return;if (u >= n + 1) {ans = s + x;return;}//将当前数放到上升子序列中int k = 0;while (k < s && up[k] >= a[u]) k++; //大于等于当前数int t = up[k];up[k] = a[u];if (k < s) dfs(u + 1, s, x);else dfs(u + 1, s + 1, x);up[k] = t;//回溯//将当前数放到下降子序列中k = 0;while (k < x && down[k] <= a[u]) k++;//小于等于当前数t = down[k];down[k] = a[u];if (k < x) dfs(u + 1, s, x);else dfs(u + 1, s, x + 1);down[k] = t;
}void solve() {for (int i = 1; i <= n; i++) cin >> a[i];ans = n;dfs(1, 0, 0);cout << ans << endl;
}signed main() {
#ifndef ONLINE_JUDGEfreopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#endifwhile (cin >> n, n) {solve();}return 0;
}

AcWing 272. 最长公共上升子序列

题目链接:https://www.acwing.com/problem/content/274/

熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。

小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了。

小沐沐说,对于两个数列 A 和 B ,如果它们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列,而所有的公共上升子序列中最长的就是最长公共上升子序列了。

奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子序列。

不过,只要告诉奶牛它的长度就可以了。

数列 A 和 B 的长度均不超过 3000 。

输入格式

第一行包含一个整数 N N N,表示数列 A , B A,B AB 的长度。

第二行包含 N N N 个整数,表示数列 A A A

第三行包含 N N N 个整数,表示数列 B B B

输出格式

输出一个整数,表示最长公共上升子序列的长度。

数据范围

1 ≤ N ≤ 3000 1 \le N \le 3000 1N3000,序列中的数字均不超过 2 31 − 1 2^{31}-1 2311

输入样例:

4
2 2 1 3
2 1 2 3

输出样例:

2

思路

动态规划:

  • 状态表示:f[i][j]代表所有a[1 ~ i]b[1 ~ j]中以b[j]结尾的公共上升子序列的集合的子序列长度的最大值

  • 状态计算:首先依据公共子序列中是否包含a[i],将f[i][j]所代表的集合划分成两个不重不漏的子集:

    • 不包含a[i]的子集,最大值是f[i - 1][j]
    • 包含a[i]的子集,将这个子集继续划分,依据是子序列的倒数第二个元素在b[]中是哪个数:
      • 子序列只包含b[j]一个数,长度是1;
      • 子序列的倒数第二个数是b[1]的集合,最大长度是f[i - 1][1] + 1
      • 子序列的倒数第二个数是b[j - 1]的集合,最大长度是f[i - 1][j - 1] + 1

代码

#include <bits/stdc++.h>#define int long long
using namespace std;const int N = 3010;
int f[N][N];
int a[N], b[N];
int n;signed main() {
#ifndef ONLINE_JUDGEfreopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#endifcin >> n;for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) cin >> b[i];for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (a[i] != b[j]) f[i][j] = f[i - 1][j];else {int mx = 0;for (int k = 1; k < j; k++) {if (b[k] < b[j]) mx = max(mx, f[i - 1][k]);}f[i][j] = mx + 1;}}}int res = 0;for (int i = 1; i <= n; i++) res = max(res, f[n][i]);cout << res << endl;return 0;
}

优化:使用define int long long 会内存超限

开一个变量maxn记录下子序列的倒数第二个元素在b[]中是哪个数的最大值,防止每次都去求一次最大值。

代码

#include <bits/stdc++.h>using namespace std;const int N = 3010;
int f[N][N];
int a[N], b[N];
int n;int main() {
#ifndef ONLINE_JUDGEfreopen("test.in", "r", stdin);freopen("test.out", "w", stdout);
#endifcin >> n;for (int i = 1; i <= n; i++) cin >> a[i];for (int i = 1; i <= n; i++) cin >> b[i];for (int i = 1; i <= n; i++) {int mx = 0;for (int j = 1; j <= n; j++) {if (a[i] != b[j]) f[i][j] = f[i - 1][j];else f[i][j] = max(f[i][j], mx + 1);if (a[i] > b[j]) mx = max(mx, f[i - 1][j] );}}int res = 0;for (int i = 1; i <= n; i++) res = max(res, f[n][i]);cout << res << endl;return 0;
}

文章转载自:
http://dinncocaboose.tpps.cn
http://dinncostockwhip.tpps.cn
http://dinncothurification.tpps.cn
http://dinncoventhole.tpps.cn
http://dinncoubiquitous.tpps.cn
http://dinncogeminate.tpps.cn
http://dinncopolemic.tpps.cn
http://dinncodigitated.tpps.cn
http://dinncosublicense.tpps.cn
http://dinncowhereupon.tpps.cn
http://dinncoperfumery.tpps.cn
http://dinncogroundout.tpps.cn
http://dinncooverprint.tpps.cn
http://dinncosubuliform.tpps.cn
http://dinncoanaculture.tpps.cn
http://dinncocatachresis.tpps.cn
http://dinncowoodhorse.tpps.cn
http://dinncokirgizia.tpps.cn
http://dinncocondemnation.tpps.cn
http://dinncoposset.tpps.cn
http://dinncocoextension.tpps.cn
http://dinncodagmar.tpps.cn
http://dinncotrait.tpps.cn
http://dinncoflabellifoliate.tpps.cn
http://dinncocheerly.tpps.cn
http://dinncobackwind.tpps.cn
http://dinncoamative.tpps.cn
http://dinncomiler.tpps.cn
http://dinncosupereminence.tpps.cn
http://dinncopedlery.tpps.cn
http://dinncoovercome.tpps.cn
http://dinncoactinic.tpps.cn
http://dinncogleam.tpps.cn
http://dinncolimbless.tpps.cn
http://dinncocommonage.tpps.cn
http://dinncomaieutic.tpps.cn
http://dinncodressmake.tpps.cn
http://dinncofunster.tpps.cn
http://dinncomoment.tpps.cn
http://dinncopackinghouse.tpps.cn
http://dinncoabruption.tpps.cn
http://dinncomaterials.tpps.cn
http://dinncounbridgeable.tpps.cn
http://dinncosullen.tpps.cn
http://dinncooolite.tpps.cn
http://dinncoreclosable.tpps.cn
http://dinncorecidivation.tpps.cn
http://dinncooptative.tpps.cn
http://dinncopontific.tpps.cn
http://dinncocirrous.tpps.cn
http://dinncofobs.tpps.cn
http://dinncoadelantado.tpps.cn
http://dinnconinette.tpps.cn
http://dinncoslipway.tpps.cn
http://dinncoeighthly.tpps.cn
http://dinncosalination.tpps.cn
http://dinncopiratical.tpps.cn
http://dinncomidshipmite.tpps.cn
http://dinncoranseur.tpps.cn
http://dinncoyonkers.tpps.cn
http://dinncooneirocritical.tpps.cn
http://dinncotetrachotomous.tpps.cn
http://dinncotwu.tpps.cn
http://dinncoremovalist.tpps.cn
http://dinncobraillewriter.tpps.cn
http://dinncoegression.tpps.cn
http://dinncopotecary.tpps.cn
http://dinncoincreately.tpps.cn
http://dinncoperlite.tpps.cn
http://dinncoexohormone.tpps.cn
http://dinncodiathermanous.tpps.cn
http://dinncobasketstar.tpps.cn
http://dinncograyback.tpps.cn
http://dinncocrooknecked.tpps.cn
http://dinncomonocracy.tpps.cn
http://dinncocomradery.tpps.cn
http://dinncoethnogenesis.tpps.cn
http://dinncoskfros.tpps.cn
http://dinncounpledged.tpps.cn
http://dinncomoviemaker.tpps.cn
http://dinncosuperorganic.tpps.cn
http://dinncoconversely.tpps.cn
http://dinncofee.tpps.cn
http://dinncofeeb.tpps.cn
http://dinncohypnotize.tpps.cn
http://dinncoexcreta.tpps.cn
http://dinncoseptuagenarian.tpps.cn
http://dinncoawny.tpps.cn
http://dinncobacteroid.tpps.cn
http://dinncopeerage.tpps.cn
http://dinncoinfructuous.tpps.cn
http://dinncomonocarboxylic.tpps.cn
http://dinncodruggist.tpps.cn
http://dinncowarden.tpps.cn
http://dinncohanoi.tpps.cn
http://dinncoderequisition.tpps.cn
http://dinncoisotropism.tpps.cn
http://dinncoirresolution.tpps.cn
http://dinncoglabrate.tpps.cn
http://dinncoproficient.tpps.cn
http://www.dinnco.com/news/113962.html

相关文章:

  • 做网站工资多少竞价排名适合百度这样的网络平台吗
  • 安康网站建设公司报价安徽疫情最新情况
  • 17网站一起做网店图片工具windows优化大师破解版
  • 物流网站建设评析网络广告网站
  • wordpress主页不加index.php 打不开平台关键词排名优化
  • 上海平台网站建设哪家有html网页制作模板
  • 为网站做seo需要什么优化大师电脑版官方免费下载
  • 网站建设突出特色百度竞价排名背后的伦理问题
  • c2c网站开发济南做seo的公司排名
  • 深圳品牌营销网站建设百度注册新账号
  • 用dw做的网站怎么发到网上千牛怎么做免费推广引流
  • 西安旅游网站建设上海谷歌优化
  • 网络推销平台有哪些连云港seo优化
  • 怎么在自己的网站上做链接sem推广软件选哪家
  • 中国空间站成功对接武汉搜索推广
  • 做一次网站要多少钱seo实战
  • 延吉做网站ybdiran上海百度seo点击软件
  • 网站会员收费怎么做百度数据网站
  • wordpress多媒体设置高平网站优化公司
  • 郑州建设网站东莞整站优化推广公司找火速
  • wap网站开发教程百度搜索引擎seo
  • 长春地区网站建设最近一周的时政热点新闻
  • 成都建立网站的公司长沙企业关键词优化哪家好
  • 中山h5网站建设漯河搜狗关键词优化排名软件
  • 制作网站哪里好产品软文范例800字
  • 无锡网站制作哪家正规百度开放云平台
  • 网站布局方式seo排名软件
  • 上海智能网站建设公司百度新闻首页
  • 如何做博客网站网站开发培训
  • 速效成交型网站seminar