区间DP---多边形 与金字塔

多边形:https://www.acwing.com/problem/content/285/

其实就是环形的石子合并,只不过由于乘法的存在还要记录一下最大值与最小值。

AC代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int a[105];
char b[105];
int dpmax[105][105];
int dpmin[105][105];
int main()
{
    int n; 
    int ret = 0;
    scanf("%d",&n);
    for(int i = 1; i <= 2*n; ++i) {
        if(i % 2 == 1) {
            cin>>b[(i/2)+1];
            b[(i/2)+1+n] = b[(i/2)+1];
        } 
        if(i % 2 == 0) {
            cin>>a[i/2];
            a[i/2+n] = a[i/2];
        }
    }
    memset(dpmax,0xc0,sizeof(dpmax));
    memset(dpmin,0x3f,sizeof(dpmin));
    for(int i = 1; i <= 2*n; ++i) {
        dpmax[i][i] = a[i];
        dpmin[i][i] = a[i];
    }
    for(int len = 1; len <= n; ++len)
        for(int l = 1; l + len <= 2*n; ++l) {
            int r = l + len;
            for(int k = l; k < r; ++k) {
                if(b[k+1] == 't') {
                    dpmax[l][r] = max(dpmax[l][r],dpmax[l][k] + dpmax[k+1][r]);
                    dpmin[l][r] = min(dpmin[l][r],dpmin[l][k] + dpmin[k+1][r]);
                } else {
                    dpmax[l][r] = max(dpmax[l][r],dpmax[l][k]*dpmax[k+1][r]);
                    dpmax[l][r] = max(dpmax[l][r],dpmin[l][k]*dpmin[k+1][r]);
                    dpmin[l][r] = min(dpmin[l][r],dpmin[l][k]*dpmin[k+1][r]);
                    dpmin[l][r] = min(dpmin[l][r],dpmax[l][k]*dpmin[k+1][r]);
                    dpmin[l][r] = min(dpmin[l][r],dpmin[l][k]*dpmax[k+1][r]);
                }
            }
        }
    for(int i = 1; i <= n; ++i) ret = max(ret,dpmax[i][i+n-1]);
    printf("%d\n",ret);
    for(int i = 1; i <= n; ++i) 
        if(dpmax[i][i+n-1] == ret) printf("%d ",i);
}

金字塔:https://www.acwing.com/problem/content/286/

显然,我们令表示DFS序列为区间的树的集合(由DFS知道连续的)

下面是状态的计算,我们以最右的子树为划分即可。

怎么划分?我们先固定最右一点,向左找与r相同的边界k()(非空)同时k属于偶数(由DFS序性质)。用乘法原理相乘即可:

AC代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod=1e9;
string s;
ll dp[330][330];
int main(){
    cin>>s;
    int n=s.size();
    if(n%2==0) cout<<0<<endl;
    else{
        for(int len=1;len<=n;len+=2){
            for(int l=0;l+len-1<n;l++){
                int r=l+len-1;
                if(len==1) dp[l][l]=1;
                else if(s[l]==s[r]){
                    for(int k=l;k<r;k+=2){
                        if(s[k]==s[r]){
                            dp[l][r]=(dp[l][r]+dp[l][k]*dp[k+1][r-1]%mod)%mod;
                        }
                    }
                }
            }
        }
        cout<<dp[0][n-1];
    }
    
}
相关推荐
oier_Asad.Chen几秒前
【OI学习笔记】Floyed-Warshall算法解决传递闭包问题
c++·笔记·学习·算法·图论·最短路·传递闭包
国科安芯1 分钟前
卫星星务计算机数据管理中SEU容错机制的技术实现研究——以AS32S601存储器ECC架构为例
网络·单片机·算法·fpga开发·架构·云计算·risc-v
孙启超6 分钟前
【AI应用开发】Agent 无限 loop(反复调用同一个工具)如何规避?
人工智能·python·算法·llm·agent·loop·ai应用开发
zmzb010319 分钟前
C++课后习题训练记录Day179
开发语言·c++
小月土星26 分钟前
LeetCode 142. 环形链表 II 超详细题解(快慢指针原理+逐行代码拆解)
算法
dok1237 分钟前
Johannes 《Linux内核模块与设备驱动开发:编写Linux驱动程序》 (11)kmalloc 动态内存分配和struct file中的私有数据
linux·驱动开发·算法
hansang_IR40 分钟前
【题解】[COCI 2024/2025 #2] 流明 / Blistavost
c++·算法·动态规划·dp
不正经学生1 小时前
C语言指针进阶:const 和野指针——给指针加锁,向野指针宣战
c语言·开发语言·c++·算法·c#
程序喵大人1 小时前
【C++进阶】STL算法与函数对象 - 01 让算法去处理一段迭代器范围
开发语言·c++·算法·函数对象
Keven_111 小时前
算法札记:二叉树前序、中序、后序遍历及对应序列重要性质
数据结构·算法·深度优先