• 洛谷 P2308 添加括号


    题目传送门

    区间DP,f[i][j]表示i~j区间最小答案,用ans[i][j]记录f[i][j]的断点在哪里,即括号分界处.

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    int n,a[21],f[21][21],pre[21],be[21],c[21];
    int ans[21][21],tot,kk[21][21];
    struct kkk{
        int v,jl;
        kkk() {
            v = 0;
            jl = 0;
        }
    }da[21];
    
    inline void dfs(int x,int y) {
        if(x == y) return ;
        pre[x]++;
        be[y]++;
        da[++tot].jl = y - x + 1;
        da[tot].v = a[y] - a[x-1];
        dfs(x,ans[x][y]);
        dfs(ans[x][y] + 1,y);
    }
    
    inline bool cmp(kkk a,kkk b) {
        return a.jl < b.jl;
    }
    
    int main() {
        memset(f,0x3f3f3f,sizeof(f));
        scanf("%d",&n);
        for(int i = 1;i <= n; i++) {
            scanf("%d",&c[i]);
            a[i] = a[i-1] + c[i];
            f[i][i] = 0;
        }
        for(int len = 1;len <= n; len++)
            for(int i = 1,j = i + len;j <= n; i++,j++)
                for(int k = i;k < j; k++)
                    if(f[i][j] >= f[i][k] + f[k+1][j] + a[j] - a[i-1]) {
                        f[i][j] = f[i][k] + f[k+1][j] + a[j] - a[i-1];
                        ans[i][j] = k;
                    }
        dfs(1,n);
        for(int i = 1;i <= n; i++) {
            while(pre[i]--)
                printf("(");
            printf("%d",c[i]);
            while(be[i]--)
                printf(")");
            if(i != n) printf("+");
        }
        printf("
    %d
    ",f[1][n]);
        sort(da+1,da+tot+1,cmp);
        for(int i = 1;i <= tot; i++)
            printf("%d ",da[i].v);
        return 0;
    }
    50分
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    int n,a[21],f[21][21],pre[21],be[21],c[21];
    int ans[21][21],tot,kk[21][21];
    
    inline void dfs(int x,int y) {
        if(x == y) return ;
        pre[x]++;
        be[y]++;
        dfs(x,ans[x][y]);
        dfs(ans[x][y] + 1,y);
    }
    
    inline void dd(int x,int y) {
        if(x == y) return ;
        dd(x,ans[x][y]);
        dd(ans[x][y] + 1,y);
        printf("%d ",a[y] - a[x-1]);
    }
    
    int main() {
        memset(f,0x3f3f3f,sizeof(f));
        scanf("%d",&n);
        for(int i = 1;i <= n; i++) {
            scanf("%d",&c[i]);
            a[i] = a[i-1] + c[i];
            f[i][i] = 0;
        }
        for(int i = 1;i <= n; i++)
            f[i][i+1] = a[i+1] - a[i-1],ans[i][i+1] = i;
        for(int len = 2;len <= n; len++)
            for(int i = 1,j = i + len;j <= n; i++,j++)
                for(int k = i;k < j; k++)
                    if(f[i][j] >= f[i][k] + f[k+1][j] + a[j] - a[i-1]) {
                        f[i][j] = f[i][k] + f[k+1][j] + a[j] - a[i-1];
                        ans[i][j] = k;
                    }
        dfs(1,n);
        for(int i = 1;i <= n; i++) {
            while(pre[i]--)
                printf("(");
            printf("%d",c[i]);
            while(be[i]--)
                printf(")");
            if(i != n) printf("+");
        }
        printf("
    %d
    ",f[1][n]);
        dd(1,n);
        return 0;
    }
    AC代码

    100分和50分之间的区别在于第三问,题目中说要从左到右输出,而50分做法可能出现同级括号间从右到左的答案

  • 相关阅读:
    Linux第七周学习总结——可执行程序的装载
    《深入理解计算机系统》第七章读书笔记
    《Linux内核设计与实现》第三章读书笔记
    《Linux内核设计与实现》第十八章读书笔记
    Linux第六周学习总结——进程额管理和进程的创建
    Linux第五周学习总结——扒开系统调用的三层皮(下
    《Linux内核设计与实现》第五章读书笔记
    #Linux第四周学习总结——扒开系统调用的三层皮(上)
    《Linux内核设计与实现》第一二章读书笔记
    Linux第三周学习总结——构造一个简单的Linux系统MenuOS
  • 原文地址:https://www.cnblogs.com/lipeiyi520/p/13604629.html
Copyright © 2020-2023  润新知