寒假:Day6

Day6

最长公共子序列

状态表示: f [ i , j ] f[i, j] f[i,j] 所有从 A [ 1..... i ] A[1.....i] A[1.....i] B [ 1..... j ] B[1.....j] B[1.....j] 的公共子序列的集合
集 合 划 分 = { A [ i ] 包 含 , B [ j ] 包 含 ( f [ i − 1 , j − 1 ] + 1 ) A [ i ] 包 含 , B [ j ] 不 包 含 ( f [ i , j − 1 ] ) A [ i ] 不 包 含 , B [ j ] 包 含 ( f [ i − 1 , j ] ) A [ i ] 不 包 含 , B [ j ] 也 不 包 含 ( f [ i − 1 , j − 1 ] ) 集合划分=\left\{ \begin{matrix} A[i]包含,B[j]包含 && (f[i - 1, j - 1] + 1)\\ A[i]包含,B[j]不包含 && (f[i, j - 1])\\ A[i]不包含,B[j]包含 && (f[i - 1, j]) \\ A[i]不包含,B[j]也不包含 &&(f[i - 1 , j - 1])\end{matrix} \right. =A[i]B[j]A[i]B[j]A[i]B[j]A[i]B[j](f[i1,j1]+1)(f[i,j1])(f[i1,j])(f[i1,j1])
所以可得状态转移方程:
f [ i , j ] = m a x ( f [ i − 1 , j − 1 ] + 1 , f [ i , j − 1 ] , f [ i − 1 , j ] , f [ i − 1 , j − 1 ] ) f[i, j] = max(f[i - 1, j - 1] + 1, f[i, j - 1], f[i - 1, j], f[i - 1,j - 1]) f[i,j]=max(f[i1,j1]+1,f[i,j1],f[i1,j],f[i1,j1])
第二和第三个集合的状态表示是无法直接表示出来的,但是状态划分虽然一般是不充不漏的,但是我们是求最大值,所以可以重但是不能漏,所以第二和第三种状态表示只是包括了那两个集合,也包含了部分其他的,而恰好第四种情况其实已经在第二三种情况时计算过了,所以不用重复计算:
f [ i , j ] = m a x ( f [ i − 1 , j − 1 ] + 1 , f [ i − 1 , j ] , f [ i , j − 1 ] ) ; f[i, j] = max(f[i - 1, j - 1] + 1, f[i - 1, j], f[i , j - 1]); f[i,j]=max(f[i1,j1]+1,f[i1,j],f[i,j1]);

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int f[N][N];
char a[N], b[N];

int main(void)
{
    
    
    cin >> n >> m >> a + 1 >> b + 1; // 下标从1开始
    for (int i = 1; i <= n; i++) {
    
    
        for (int j = 1; j <= m; j++) {
    
    
            f[i][j] = max(f[i - 1][j], f[i][j - 1]);
            // 如果此时a[i] = b[j]时,才存在第1种情况
            if (a[i] == b[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
        }
    }
    cout << f[n][m] << endl ;
    return 0;
}

最长公共上升子序列

状态表示: f [ i , j ] f[i, j] f[i,j] 表示所有在 A [ 1...... i ] A[1......i] A[1......i] 中和 B [ 1...... j ] B[1......j] B[1......j] 中都出现过,且以 B [ j ] B[j] B[j] 结尾的公共上升子序列的集合
集 合 划 分 = { 不 包 含 A [ i ] 的 公 共 子 序 列 ( f [ i − 1 , j ] ) 包 含 A [ i ] 的 公 共 子 序 列 ( m a x ( f [ i − 1 , 1.... j ] + 1 ) ) 集合划分=\left\{\begin{matrix} 不包含A[i]的公共子序列 & (f[i - 1, j]) \\ \\包含A[i]的公共子序列 &(max(f[i - 1, 1....j] + 1))\end{matrix} \right. =A[i]A[i](f[i1,j])(max(f[i1,1....j]+1))
不包含 A [ i ] A[i] A[i] 的集合很好理解,跟具定义出发就是 f [ i − 1 , j ] f[i - 1, j] f[i1,j] ,包含 A [ i ] A[i] A[i] 在什么情况下才存在呢?只有在 A [ i ] = B [ j ] A[i] = B[j] A[i]=B[j] 时才存在,因为是以 B [ j ] B[j] B[j] 结尾,然后我们怎么去找这个集合中的最大,就是从 1 1 1 j j j 找一个max即可,朴素版是需要三层循环的,在枚举 1 1 1 j j j 时我们可以考虑前缀和的思想去用一个 m a x v maxv maxv 去把每一次的遍历的最大值都存起来,这样就不用每一次都去遍历了减少了时间复杂度

#include<bits/stdc++.h>
using namespace std;
const int N = 3010;
int a[N], b[N], f[N][N], n;
int main(void)
{
    
    
    cin >> 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 maxv = 1;
        for (int j = 1; j <= n; j++) {
    
    
            f[i][j] = f[i - 1][j]; // 先让f[i][j]等于左边集合
            if (a[i] == b[j]) f[i][j] = max(maxv, f[i][j]); //如果右边集合存在,再次更新f[i][j]
            if (b[j] < a[i]) maxv = max(maxv, f[i - 1][j] + 1); //如果当前值小于a[i],那就更新maxv
        }
    }
    int res = 0;
    for (int i = 1; i <= n; i++) res = max(res, f[n][i]);
    //因为b[j]是一定被选,所以要枚举取最大值
    cout << res << endl ;
    return 0;
}

OK,准备回归背包问题!

明天叭,今天感觉什么都没干,就过去了,放点水题上来水水博客,比如AcWing周赛 [滑稽.jpg]

4200. 简单问题 - AcWing题库

#include<bits/stdc++.h>
using namespace std;

int main(void)
{
    
    
    int p1, p2, p3, p4, a, b;
    if (a > b) swap(a, b);
    cin >> p1 >> p2 >> p3 >> p4 >> a >> b;
    int c = min(p1, min(p2, min(p3, p4))) - 1;
    if (c < a) puts("0");
    else if (a <= c && c <= b) printf("%d", c - a + 1);
    else printf("%d", b - a + 1);
    return 0;
}

4201. 01数 - AcWing题库

#include<bits/stdc++.h>
using namespace std;
int n ;
int res = 1;

void dfs(int x) 
{
    
    
    if (x * 10 <= n) {
    
    
        res ++ ;
        dfs(x * 10);
    }
    if (x * 10 + 1 <= n) {
    
    
        res ++;
        dfs(x * 10 + 1);
    }
}

int main(void)
{
    
    
    cin >> n;
    dfs(1);
    cout << res << endl ;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hjh2020012124/article/details/122149972