首页 > 其他分享 >区间DP入门

区间DP入门

时间:2023-11-05 14:11:22浏览次数:49  
标签:f2 入门 int 最大值 len ans 区间 DP op

石子合并

别人讲过太多了,蒟蒻就不说了。

Polygon

这题跟石子合并类似,只是多输出了个先清除哪条边可以使得值最大。

因为我们不确定先删那一条,我们就再复制一遍添到输入的结尾,就变成了 $2 \times N - 1$。

我们思考最大值是由哪些贡献的。

  1. 最大值与最大值运算。
  2. 最小值乘上最小值(因为当负数乘上负数时,会变为正数)。

那么最小值。

  1. 最大值乘上最小值(当最大值为正数时,反而会更小)。
  2. 最小值加上最

我们设 $f1_{i,j}$ 为以 $i$ 为左端点 $j$ 为右端点这个区间内的最大值, $f2_{i,j}$ 为最小值。

定义一个函数:

int deal(int x, int y, int op) {
	if (op == 't') return x + y;
	return x * y;
}

动态转移方程是
$$f1(i,j) = \max(deal(f1(k+1,j), f1(i,k),op_{k+1}),deal(f2(k + 1,j), f2(i,k),op_{k + 1}))$$

$$f2_(i,j) = \min(deal(f2(k+1,j), f2(i,k),op_{k+1}),deal(f1_(k + 1,j), f2_(i,k),op_{k + 1}))$$

最后我们去寻找以 $i$ 为起点的,长度为 $n$ 的最大值,如果等于最后答案,那么便输出,因为这样一定能删去第 $i$ 条边,得到最大值。

串折叠 Folding&秘密文件&[SCOI2003] 字符串折叠

三倍经验,快乐。

就拿第一个讲。

我们设 $dp[i][j]$ 表示字符串中 $s[i\sim j]$ 折叠后的最小长度。

它可以有两种方式转移而来:

  1. 由两段子串折叠后的最小长度加起来。
  2. 以一段子串为循环元,然后出折叠后的长度。

我们通过:

for (int i = l; i + k <= r; i++) {
	if (s[i] != s[i + k]) return 0;
}
return 1;

去找到循环元。

于是:
$$dp[i][j] = min(dp[i][k] + dp[k+1][j], dp[i][k] + 2 + m[(j - i + 1) \div (k - i + 1])$$
其中,$m$ 数组时每个数的位数。因为 $s[i\sim k]$ 为循环元,那么就会有 $(j - i + 1) \div (k - i + 1)$ 个循环元,再加上括号的个数,便为折叠后的个数。

我们还要求出字符串是什么,那么在转移时加上即可。

上代码:

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

const int N = 200;
int n, f[N][N], m[N];
string s, ans[N][N];

bool check(int l, int r, int k) {
    for (int i = l; i + k <= r; i++) {
        if (s[i] != s[i + k]) return 0;
    }
    return 1;
}

string shu(int x) {//求出数字的字符串
    string res = "";
    while (x) {
        res = char(x % 10 + '0') + res;
        x /= 10;
    }
    return res;
}

int main() {
    for (int i = 1; i <= 9; i++) m[i] = 1;
    for (int i = 10; i < 100; i++) m[i] = 2;
    for (int i = 100; i <= 199; i++) m[i] = 3;
	while (cin >> s) {
		n = s.size();
		s = " " + s;
		for (int l = 0; l < n; l++) {//区间DP
			for (int i = 1; i + l <= n; i++) {
				int j = l + i;
				f[i][j] = l + 1;
                ans[i][j] = s.substr(i, l + 1);//初始化
                for (int k = i; k < j; k++) {
                    if (f[i][j] > f[i][k] + f[k + 1][j]) {
                        f[i][j] = f[i][k] + f[k + 1][j];
                        ans[i][j] = ans[i][k] + ans[k + 1][j];//求出字符串
                    }
                    else if (f[i][j] == f[i][k] + f[k + 1][j]) {
                        ans[i][j] = max(ans[i][j], ans[i][k] + ans[k + 1][j]);//如果个数相同,找到字典序最大的一项。
                    }
                }
				for (int k = i; k < j; k++) {
					int len = k - i + 1;
                    if ((l + 1) % len == 0 && check(i, j, len)) {
                        string sub = shu((l + 1) / len) + '(' + ans[i][k] + ')';//以 s[i~k] 为循环元的字符串
                        if (f[i][j] > f[i][k] + 2 + m[(l + 1) / len]) {
                            f[i][j] = min(f[i][j], f[i][k] + 2 + m[(l + 1) / len]);
                            ans[i][j] = sub;
                        }
                        else if (f[i][j] == f[i][k] + 2 + m[(l + 1) / len]) ans[i][j] = max(ans[i][j], sub);//如果个数相同,找到字典序最大的一项。
                    }
				}
			}
		}
		cout << ans[1][n] << '\n';
	}
	return 0;
}

标签:f2,入门,int,最大值,len,ans,区间,DP,op
From: https://www.cnblogs.com/luckycloud/p/17810472.html

相关文章

  • Git入门笔记--版本控制系统的使用
    首先记录下使用命令行工具git与github交互的“Hello,World!”。"Hello,World!"是任何程序设计语言入门第一课,不管原理,先跑起来再说。git的"Hello,World!"就是如何从github获取仓库到本地,并将修改上传github。1.将远程仓库clone到本地:$gitclone<仓库地址>这条git命令行......
  • ctfshow——misc入门(1)
    2打开看见IHDR发现是PNG格式直接重命名,然后用honeyview解出来 3.与第二题解法一样方法思路都是一样的4.利用010editor寻找文件头——通过对比文件头表确定文件类型,再重命名得到文件。png——文件头89504E47jpg——文件头FFD8FFBMP——文件头424DGIF——文......
  • 笛卡尔树入门
    笛卡尔树的定义笛卡尔树是一种二叉树,每一个结点由一个键值二元组\((k,w)\)构成。要求\(k\)满足二叉搜索树的性质,而\(w\)满足堆的性质。一个有趣的事实是,如果笛卡尔树的\(k,w\)键值确定,且\(k\)互不相同,\(w\)互不相同,那么这个笛卡尔树的结构是唯一的。——OIwiki笛......
  • 有趣的Java之网络多线程——UDP编程
    UDP编程通信基本介绍类DatagramSocket和DatagramPacket【数据包/数据报】实现了基于UDP协议网络程序。UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能安全送到目的地,也不确信什么时候可以抵达。DatagramPacket对象封装了UDP数据报,在数据报中包含了发......
  • 状态压缩DP
    关于状态表示形式的优化方式。使用场景:需要记录不超过二进制数位(通常22位以内)的bool信息的DP问题。常见的位操作简单操作任何二进制数位&1得到它本身。任何二进制数位^1则取反。任何二进制数位&0则赋值为0。任何二进制数位|1则赋值为1。混合操作(n>>k&1)......
  • 推荐一些socket工具,TCP、UDP调试、抓包工具
    推荐一些socket工具,TCP、UDP调试、抓包工具https://www.cnblogs.com/porter/p/7838753.html如何使用TCP|UDPSOCKET调试工具联机超高频读卡器HXU7881-6DBI/IPhttps://zhuanlan.zhihu.com/p/648752372?utm_id=0......
  • 【Flutter入门到精通】全网独一份Flutter学习笔记,重磅来袭
    前言随着纯客户端到Hybrid技术,到RN&Weex,再到如今的Flutter技术,客户端实现技术不断前进。在之前的一个APP项目中,因为历史原因当时选择了weex,随着使用的不断深入,我们逐渐发现了weex的渲染性能问题已经成为一个隐患和瓶颈。而Flutter技术的不断成熟和流行,Flutter的良好的跨平台性和......
  • TensorFlow 入门 ---- 手势识别
    原文:https://www.jianshu.com/p/298d8122ca62?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation学习笔记来自于何宽大佬的学习笔记本文的相关资料来自于何宽大佬的百度云1-导入TensorFlow库importnumpyasnpimporth5pyimp......
  • python实现手势识别的示例(入门)
    原文:https://pythonjishu.com/yoprvijnxxyihab/手势识别是计算机视觉领域的一个重要研究方向。在实际应用中,手势识别可以被用于人机交互、智能家居控制等领域。在本文中,我们将介绍如何使用Python实现手势识别的示例代码。环境搭建安装Python要使用Python进行手势识别的开发,首......
  • Shell的基本操作和编程入门
    操作:1)给变量赋值,练习echo命令,做下面这个题目:安装中文输入环境:http://rpm.pbone.net  选择第二个,点击右键,复制地址: 按顺序输入下面的命令:     安装完成后,输入zhcon,进入中文输入环境 a)把自己的名字赋值给变量name,把"是"赋值给变量is,把自己的班级名称......