「刷题记录」LOJ/一本通提高篇 区间类动态规划
「石子合并」#
题目传送门:石子合并
状态: : 第 堆到第 堆合并的最优解
点击查看代码
/*
date: 2022.8.31
worked by yi_fan0305
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 500;
const int inf = ~(1 << 31);
int n, maxn, minn = inf;
int w[N], dp_max[N][N], dp_min[N][N], qsum[N];
inline ll read() {
ll x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
int main() {
n = read();
memset(dp_min, 127, sizeof dp_min);
memset(dp_max, 128, sizeof dp_max);
for (int i = 1; i <= n; ++i) {
w[i] = read();
w[i + n] = w[i];
dp_max[i][i] = dp_min[i][i] = 0;
qsum[i] = qsum[i - 1] + w[i];
}
for (int i = n + 1; i <= (n << 1); ++i) {
dp_max[i][i] = dp_min[i][i] = 0;
qsum[i] = qsum[i - 1] + w[i];
}
for (int len = 1; len < n; ++len) {
for (int i = 1; i + len <= (n << 1); ++i) {
int j = i + len;
for (int k = i; k < j; ++k) {
dp_max[i][j] = max(dp_max[i][j], dp_max[i][k] + dp_max[k + 1][j] + qsum[j] - qsum[i - 1]);
dp_min[i][j] = min(dp_min[i][j], dp_min[i][k] + dp_min[k + 1][j] + qsum[j] - qsum[i - 1]);
}
}
}
for (int i = 1; i <= n; ++i) {
maxn = max(maxn, dp_max[i][i + n - 1]);
minn = min(minn, dp_min[i][i + n - 1]);
// cout << dp_max[i][i + n - 1] << " " << dp_min[i][i + n - 1] << endl;
}
printf("%d\n%d", minn, maxn);
return 0;
}
「能量项链」#
题目传送门:能量项链
状态: : 第 颗能量石到第 颗能量石合并释放的最大能量
点击查看代码
/*
date: 2022.8.31
worked by yi_fan0305
*/
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 310;
int n, ans;
int w[N], he[N], ti[N], dp[N][N];
inline ll read() {
ll x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
int main() {
n = read();
for (int i = 1; i <= n; ++i) {
w[i] = read();
w[i + n] = w[i];
}
for (int i = 1; i <= (n << 1); ++i) {
he[i] = w[i];
ti[i] = w[i + 1];
}
ti[n << 1] = he[1];
for (int len = 1; len < n; ++len) {
for (int i = 1; i + len <= (n << 1); ++i) {
int j = i + len;
for (int k = i; k < j; ++k) {
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j] + he[i] * ti[k] * ti[j]);
}
}
}
for (int i = 1; i <= n; ++i) {
ans = max(ans, dp[i][i + n - 1]);
}
printf("%d\n", ans);
return 0;
}
「凸多边形的划分」#
题目传送门:凸多边形的划分
状态: : 第 个点 到第 个点划分成三角形的最小乘积和
点击查看代码
/*
date: 2022.8.31
worked by yi_fan0305
*/
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 110;
const ll inf = ~(1ll << 63);
int n;
__int128 ans = 1e30;
__int128 w[N], ji[N], qsum[N], dp[N][N];
inline __int128 read() {
__int128 x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
void print(__int128 x) {
if (x < 0) {
x = -x;
putchar('-');
}
if (x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
int main() {
n = read();
for (int i = 1; i <= n; ++i) {
w[i] = read();
w[i + n] = w[i];
dp[i][i] = dp[i + n][i + n] = 0;
}
for (int i = 1; i <= (n << 1); ++i) {
for (int j = i + 2; j <= (n << 1); ++j) {
dp[i][j] = 1e30;
}
}
for (int len = 2; len < n; ++len) {
for (int l = 1; l + len <= (n << 1); ++l) {
int r = l + len;
for (int k = l + 1; k < r; ++k) {
dp[l][r] = min(dp[l][r], dp[l][k] + dp[k][r] + w[l] * w[k] * w[r]);
}
}
}
for (int i = 1; i <= n; ++i) {
ans = min(ans, dp[i][i + n - 1]);
}
print(ans);
return 0;
}
「括号配对」#
题目传送门:括号配对
状态: : 区间内能配对起来的符号个数
点击查看代码
/*
date: 2022.9.1
worked by yi_fan0305
*/
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <stack>
using namespace std;
typedef long long ll;
int dp[110][110];
string str;
stack<char> st;
inline ll read() {
ll x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
int main() {
cin >> str;
int siz = str.size();
for (int len = 1; len < siz; ++len) {
for (int l = 0; l + len < siz; ++l) {
int r = l + len;
if ((str[l] == '[' && str[r] == ']') || (str[l] == '(' && str[r] == ')'))
dp[l][r] = dp[l + 1][r - 1] + 2;
else
dp[l][r] = max(dp[l + 1][r], dp[l][r - 1]);
for (int k = l; k < r; ++k) {
dp[l][r] = max(dp[l][r], dp[l][k] + dp[k + 1][r]);
}
}
}
printf("%d\n", siz - dp[0][siz - 1]);
return 0;
}
「分离与合体」#
题目传送门:分离与合体
状态: : 区间内拿到金钥匙的最大价值和
用广搜来输出答案
点击查看代码
/*
date: 2022.9.1
worked by yi_fan0305
*/
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 310;
int n;
int w[N], dp[N][N], qsum[N], ans[N][N];
struct node {
int l, r;
} tmp;
inline ll read(){
ll x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
void print(int l, int r) {
queue<node> q;
tmp.l = l;
tmp.r = r;
q.push(tmp);
while(!q.empty()) {
node u = q.front();
q.pop();
if(u.l == u.r)
continue;
printf("%d ", ans[u.l][u.r]);
tmp.l = u.l, tmp.r = ans[u.l][u.r];
q.push(tmp);
tmp.l = ans[u.l][u.r] + 1, tmp.r = u.r;
q.push(tmp);
}
}
int main() {
n = read();
for (int i = 1; i <= n; ++i) {
w[i] = read();
qsum[i] = qsum[i - 1] + w[i];
}
for (int len = 1; len < n; ++len) {
for (int l = 1; l + len <= n; ++l) {
int r = l + len;
for (int k = l; k < r; ++k) {
if (dp[l][k] + dp[k + 1][r] + (w[l] + w[r]) * w[k] > dp[l][r]) {
dp[l][r] = max(dp[l][r], dp[l][k] + dp[k + 1][r] + (w[l] + w[r]) * w[k]);
ans[l][r] = k;
}
}
}
}
printf("%d\n", dp[1][n]);
print(1, n);
return 0;
}
「矩阵取数游戏」#
题目传送门:矩阵取数游戏
状态: : 区间内取 个数的最大价值
点击查看代码
/*
date: 2022.9.1
worked by yi_fan0305
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
int n, m;
__int128 ans;
__int128 w[100], dp[110][110], point[110];
inline __int128 read() {
__int128 x = 0;
int fg = 0;
char ch = getchar();
while (ch < '0' || ch > '9') {
fg |= (ch == '-');
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return fg ? ~x + 1 : x;
}
void pre() {
point[0] = 1;
for (int i = 1; i <= m; ++i) {
point[i] = point[i - 1] * 2;
}
}
void print(__int128 x) {
if(x < 0) {
x = -x;
putchar('-');
}
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
int main() {
n = read(), m = read();
pre();
for (int k = 1; k <= n; ++k) {
for (int j = 1; j <= m; ++j) {
w[j] = read();
}
memset(dp, 0, sizeof dp);
for (int i = 1; i <= m; ++i) {
for (int j = m; j >= i; --j) {
dp[i][j] = max(dp[i][j], dp[i - 1][j] + point[m - j + i - 1] * w[i - 1]);
dp[i][j] = max(dp[i][j], dp[i][j + 1] + point[m - j + i - 1] * w[j + 1]);
}
}
__int128 maxn = 0;
for (int i = 1; i <= m; ++i) {
maxn = max(maxn, dp[i][i] + point[m] * w[i]);
}
ans += maxn;
}
print(ans);
return 0;
}
作者:yifan0305
出处:https://www.cnblogs.com/yifan0305/p/16648869.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载时还请标明出处哟!
朝气蓬勃 后生可畏
分类:
刷题记录
Buy me a cup of coffee ☕.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】