动态规划五
复健
动态规划(五)区间
石子合并
https://www.acwing.com/problem/content/284/
这是区间的模板题
这道题看似和果子合并很相像,于是我们想到贪心,但是这是行不通的
因为我们每次只能合并相邻的两堆,可以在纸上画一下样例,显然是不对的
表示把从到合并成一堆的最小代价:
边界:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 310
#define inf 0x3f3f3f3f
using namespace std;
int f[maxn][maxn];
int s[maxn];
int a[maxn];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
memset(f,0x3f,sizeof(f));
for(int i=1;i<=n;i++) f[i][i]=0;
for(int len=2;len<=n;len++)//先枚举长度,再枚举左端点,最后枚举中间分割点
{
for(int l=1;l+len-1<=n;l++)
{
int r=l+len-1;
for(int k=l;k<r;k++)
{
f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
}
}
}
printf("%d\n",f[1][n]);
return 0;
}
环形石子合并
https://www.luogu.com.cn/problem/P1880
展环为链即可
注意最后输出不是和,而是要枚举起点,取最大值和最小值
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 310
#define inf 0x3f3f3f3f
using namespace std;
int f[maxn][maxn];
int g[maxn][maxn];
int s[maxn];
int a[maxn];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i];
for(int i=1;i<=2*n;i++) s[i]=s[i-1]+a[i];
memset(f,0x3f,sizeof(f));
memset(g,-0x3f,sizeof(g));
for(int i=1;i<=2*n;i++) f[i][i]=0,g[i][i]=0;
for(int len=2;len<=n;len++)
{
for(int l=1;l+len-1<=2*n;l++)
{
int r=l+len-1;
for(int k=l;k<r;k++)
{
f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+s[r]-s[l-1]);
g[l][r]=max(g[l][r],g[l][k]+g[k+1][r]+s[r]-s[l-1]);
}
}
}
int maxx=0,minv=inf;
for(int i=1;i<=n;i++) minv=min(minv,f[i][i+n-1]),maxx=max(maxx,g[i][i+n-1]);
printf("%d\n%d\n",minv,maxx);
return 0;
}
能量项链
https://www.luogu.com.cn/problem/P1063
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 210
using namespace std;
int f[maxn][maxn];
int a[maxn];
signed main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i+n]=a[i];
}
//for(int i=1;i<=2*n;i++) f[i][i]=0;
for(int len=2;len<=n;len++)
{
for(int l=1;l+len-1<=2*n;l++)
{
int r=l+len-1;
for(int k=l;k<r;k++)
{
f[l][r]=max(f[l][r],f[l][k]+f[k+1][r]+a[l]*a[k+1]*a[r+1]);
}
}
}
int maxx=0;
for(int i=1;i<=n;i++) maxx=max(maxx,f[i][i+n-1]);
printf("%d\n",maxx);
return 0;
}
注意的终止条件是,如果我写成,会可能让数组越界,而且时间复杂度也变高了
正因无所有,才会无所畏
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现