蓝桥杯刷题十五

文章展示了六个使用动态规划和树形动态规划的编程问题解决方案,包括计算字符串中非回文子串的长度、处理树的最值问题、计算斐波那契数列前n项和、解决括号匹配问题、优化旅行路线以及通过矩阵相乘快速幂解决垒骰子问题。每个问题都给出了相应的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.密码脱落

dp 结果是总长度-最大回文串的长度

#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>PII;
typedef long long ll;
const int N=1010;
int n,k;
int f[N][N];
char s[N];
int main()
{
    scanf("%s",s);
    n=strlen(s);
    for(int len=1;len<=n;len++)
        for(int i=0;i+len-1<n;i++)
    {
        int j=i+len-1;
        if(len==1) f[i][j]=1;
        else {
            f[i][j]=max(f[i+1][j],f[i][j-1]);
            if(s[i]==s[j])
            f[i][j]=max(f[i][j],f[i+1][j-1]+2);
        }
    }
    cout<<n-f[0][n-1]<<endl;
    return 0;
}

2.生命之树

树形dp

#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>PII;
typedef long long ll;
const int N=100010,M=2*N;
int e[M],ne[M],h[N],w[M];
int idx;
ll f[N];
int n;
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int father)
{
    f[u]=w[u];
    for(int i=h[u];~i;i=ne[i])
    {
        int j=e[i];
        if(j!=father)
        {
            dfs(j,u);
            f[u]+=max(0ll,f[j]);
        }
    }
}

int main()
{
    scanf("%d",&n);
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
        for(int i=1;i<=n-1;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs(1,-1);
        ll res=f[1];
        for(int i=2;i<=n;i++) res=max(res,f[i]);

        cout<<res<<endl;
    return 0;
}

3.斐波那契前 n 项和

线性代数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3;
int n,m;
int a[N][N]={
    {0,1,0},
    {1,1,1},
    {0,0,1}
};
void mul(int a[][N],int b[][N])
{
    int tmp[N][N]={0};

    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
        for(int k=0;k<N;k++)
        tmp[i][j]=(tmp[i][j]+(ll)a[i][k]*b[k][j])%m;
    memcpy(a,tmp,sizeof tmp);
}

int main()
{
   scanf("%d%d",&n,&m);
    int f1[N][N]={1,1,1};
    n--;
    while(n)
    {
        if(n&1) mul(f1,a); //相当于res*a操作
        mul(a,a);  //相当于快速幂里面的a*a操作
        n>>=1;
    }
    cout<<f1[0][2]<<endl;
return 0;
}

4.括号配对

#include <cstdio>
#include <iostream>

using namespace std;

const int N = 110, INF = 1e8;

int f[N][N];

bool is_match(char l, char r) {
    if (l == '(' && r == ')')  return true;
    if (l == '[' && r == ']')  return true;

    return false;
}

int main() {
    string s;  cin >> s;

    int n = s.size();
    for (int len = 1; len <= n; len ++) {
        for (int l = 0; l + len - 1 < n; l ++) {
            int r = l + len - 1; f[l][r] = INF;
            if (is_match(s[l], s[r]))  f[l][r] = f[l + 1][r - 1];
            if (r >= 1)  f[l][r] = min(f[l][r], min(f[l][r - 1], f[l + 1][r]) + 1);

            for (int i = l; i < r; i ++)
                f[l][r] = min(f[l][r], f[l][i] + f[i + 1][r]);
        }
    }

    return cout << f[0][n - 1] << endl, 0;
}

5.旅游规划

树形dp

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 2e5 + 10, M = 4e5 + 10;

int h[N], e[M], ne[M], idx;
int d1[N], d2[N], p1[N], up[N], maxd;

void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void dfs_d(int u, int fa) {
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j != fa) {
            dfs_d(j, u);
            int distance = d1[j] + 1;
            if (distance > d1[u]) {
                d2[u] = d1[u], d1[u] = distance;
                p1[u] = j;
            }
            else if (distance > d2[u])  d2[u] = distance;
        }
    }

    maxd = max(maxd, d1[u] + d2[u]);
}

void dfs_u(int u, int fa) {
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j != fa) {
            up[j] = up[u] + 1;
            if (p1[u] == j)  up[j] = max(up[j], d2[u] + 1);
            else             up[j] = max(up[j], d1[u] + 1);

            dfs_u(j, u);
        }
    }
}

int main() {
    int n;  scanf("%d", &n);

    memset(h, -1, sizeof h);

    for (int i = 0; i < n - 1; i ++) {
        int a, b;  scanf("%d%d", &a, &b);

        add(a, b), add(b, a);
    }

    dfs_d(0, -1), dfs_u(0, -1);

    for (int i = 0; i < n; i ++) {
        int d[3] = {d1[i], d2[i], up[i]};

        sort(d, d + 3);

        if (d[1] + d[2] == maxd)  printf("%d\n", i);
    }

    return 0;
}

6.垒骰子

dp+矩阵相乘快速幂优化

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

typedef long long LL;

const int N = 6, MOD = 1e9 + 7;

int get(int x) {
    if (x >= 3)  return x - 3;

    return x + 3;
}

void mul(int c[][N], int a[][N], int b[][N]) {  //c = a * b
    static int t[N][N];  memset(t, 0, sizeof t);

    for (int i = 0; i < N; i ++)
        for (int j = 0; j < N; j ++)
            for (int k = 0; k < N; k ++)
                t[i][j] = (t[i][j] + (LL)a[i][k] * b[k][j]) % MOD;

    memcpy(c, t, sizeof t);
}

int main() {
    int n, m;  scanf("%d%d", &n, &m);

    int a[N][N];
    for (int i = 0; i < N; i ++)
        for (int j = 0; j < N; j ++)
            a[i][j] = 4;

    while (m --) {
        int x, y;  scanf("%d%d", &x, &y);

        x --, y --;
        a[x][get(y)] = 0;
        a[y][get(x)] = 0;
    }

    int f[N][N] = {4, 4, 4, 4, 4, 4};
    for (int i = n - 1; i; i >>= 1) {
        if (i & 1)  mul(f, f, a);

        mul(a, a, a);
    }

    int res = 0;
    for (int i = 0; i < N; i ++)  res = (res + f[0][i]) % MOD;

    return printf("%d\n", res), 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值