kuangbin专题12 基础DP
Longest Ordered Subsequence
题意:有n个数,在保证原有顺序不变的前提下取出尽可能多的数,使得形成的新序列严格递增。输出取出的数个数。
题解:有两层循环,第二层循环判断第j个位置能不能要[i], 能的话就与当前值比较去max,这需要满足i位置的dp已达最优,所以第一层循环是用来保证每个dp[i]已达最优的。但是没法记录路径,也就是说最大值确实能找到,但是可能有很多路径都满足。
dp[i]:包含第i项,且第i项是最后一个被选中的的最长子序列长度。
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
#define ll long long
const int maxn = 1050;
int n, a[maxn];
ll dp[maxn];
int main()
{
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
dp[i] = 1;
}
ll maxx = 0;
//无法记录路径,也就是:最多确实是那么些个,但是到底是那几个点,情况可能有好多
for(int i = 1; i <= n; i ++) {//dp[i]已达最优
for(int j = i + 1; j <= n; j ++) {
if(a[j] > a[i]) {//a[i]能不能选
dp[j] = max(dp[i] + 1, dp[j]);
}
}
maxx = max(maxx, dp[i]);
}
cout << maxx << "\n";
return 0;
}
Super Jumping! Jumping! Jumping!
题意:给定一条长度为n的序列,其中存在一条元素和最大的严格上升子序列,求这条序列的元素和。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1050;
ll a[maxn], dp[maxn];
int main()
{
int n;
while(cin >> n && n) {
for(int i = 1; i <= n; i ++) {
cin >> a[i];
dp[i] = a[i];
}
ll maxx = 0;
for(int i = 1; i <= n; i ++) {
for(int j = i + 1; j <= n; j ++) {
if(a[j] > a[i]) {
dp[j] = max(dp[j], dp[i] + a[j]);
}
}
maxx = max(maxx, dp[i]);
}
cout << maxx << "\n";
}
return 0;
}
Common Subsequence
题意:首先对最长子序列有个定义:如果一个字符串a可以由另一个字符串b删去某些元素得到,那么说明a就是b的子序列字符串。现在有两个字符串,请问最长公共子序列是多长?
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
const int maxn = 1005;
int dp[maxn][maxn];
int main()
{
char s1[maxn], s2[maxn];
while(~scanf("%s%s",s1 + 1, s2 + 1)) {
memset(dp, 0, sizeof(dp));
int l1 = strlen(s1 + 1);
int l2 = strlen(s2 + 1);
for(int i = 1; i <= l1; i ++) {
for(int j = 1; j <= l2; j ++) {
if(s1[i] == s2[j]) dp[i][j] = dp[i - 1][j - 1] + 1;
else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
cout << dp[l1][l2] << "\n";
}
return 0;
}
题意:给出n个数,出题人想找出出现至少(n+1)/2次的数, 现在需要你帮忙找出这个数是多少?
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 20;
int a[maxn], n;
//odd:奇数 出现最多的数 - 其他数总和 >= 1
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
while (cin >> n) {
int sum = 0, ans;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
if (sum == 0) {
sum ++;
ans = a[i];
} else {
if (ans == a[i]) sum ++;
else sum --;
}
}
cout << ans << "\n";
}
return 0;
}
Phalanx
给你一个矩阵,只由小写或大写字母构成。求出它的最大对称子矩阵的边长。其中对称矩阵是一个k*k的矩阵,它的元素关于从左下角到右上角的对角线对称。
题解:dp[i][j]代表以(i,j)为右下角顶点的矩阵中,最大的对称矩阵的边长。每次dp[i][j]都以dp[i-1][j-1]为参考,只遍历一行一列,且遍历的k值小于dp[i-1][j-1]。
初始化:dp[i][j] = 1
需要注意的是,当遇到不满足对称条件的两个顶点时,循环结束。但这并不意味着dp[i][j]只能等于1,它的值应该是遍历结束时f的值 + 1。
#include<bits/stdc++.h>
using namespace std;
#define TLE std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
const int maxn = 1050;
char a[maxn][maxn];
int n;
int dp[maxn][maxn];
int main() {
TLE;
while (cin >> n && n) {
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
dp[i][j] = 1;
}
}
for (int i = n; i >= 1; i --) {
for (int j = 1; j <= n; j ++) {
cin >> a[i][j];
}
}
int maxx = 1;
for (int i = 2; i <= n; i ++) {
for (int j = 2; j <= n; j ++) {
int f = 0;
int t = dp[i - 1][j - 1];
for (int k = 1; k <= t; k ++) {
if (a[i - k][j] != a[i][j - k]) {//写成dp了
break;
}
f ++;
}
if (f) {
dp[i][j] += f;
}
maxx = max(maxx, dp[i][j]);
}
}
cout << maxx << "\n";
}
return 0;
}
FatMouse and Cheese
dfs和动规相结合的题目,深搜能保证一个节点搜索后,它的所有子路径都被访问,能保证该节点最优。
#include<bits/stdc++.h> using namespace std; const int maxn = 150; int a[maxn][maxn]; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; int dp[maxn][maxn]; int n, k; int dfs(int x, int y) { if(dp[x][y]) return dp[x][y];//已访问过的已为最优 int mx = 0; for(int i = 1; i <= k; i ++) { for(int j = 0; j < 4; j ++) { int xx = x + i * dx[j], yy = y + i * dy[j]; if(xx < 1 || xx > n || yy < 1 || yy > n) continue; if(a[xx][yy] <= a[x][y]) continue; mx = max(mx, dfs(xx, yy)); } } return dp[x][y] = mx + a[x][y]; } int main() { while(cin >> n >> k) { if(n == - 1 && k == -1) break; memset(dp, 0, sizeof(dp)); for(int i = 1; i <= n; i ++) { for(int j = 1; j <= n; j ++) { cin >> a[i][j]; } } cout << dfs(1, 1) << "\n"; } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战