石子合并
https://www.luogu.com.cn/problem/P1880
一道区间dp题目。
用d[i][j]表示从i到j的最大/最小得分,那么依次枚举长度len,坐标i和j,三层循环就可以dp递推求得最值了(听说这是道NOI题目)
记得使用前缀和哦。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<ctype.h> #define INF 0x3f3f3f3f using namespace std; inline int read() { int x=0,w=1;char c=getchar(); while(!isdigit(c)){ if(c=='-')w=-1; c=getchar(); } while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar(); return x*w; } const int maxn=105; int a[maxn],sum[maxn],d[maxn][maxn],d2[maxn][maxn]; int main() { int n=read(); for(int i=1;i<=n;i++)a[i]=read(); for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];//前缀和 for(int len=2;len<=n;len++) for(int i=1;i<=n-len+1;i++) { int j=i+len-1; d[i][j]=INF; for(int k=i;k<j;k++) { if(d[i][j]>d[i][k]+d[k+1][j]+sum[j]-sum[i-1]) d[i][j]=d[i][k]+d[k+1][j]+sum[j]-sum[i-1]; if(d2[i][j]<d2[i][k]+d2[k+1][j]+sum[j]-sum[i-1]) d2[i][j]=d2[i][k]+d2[k+1][j]+sum[j]-sum[i-1]; } } printf("%d\n%d\n",d[1][n],d2[1][n]); return 0; }
勇于实践的小伙伴们可以惊讶的发现:它爆零了!
emmm我们仔细审题会发现这是一个环。
所以不要着急我们给它再加n个数复制一遍就可以AC了(发扬了dp用内存换速度的优良作风)
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<ctype.h> #define INF 0x3f3f3f3f using namespace std; inline int read() { int x=0,w=1;char c=getchar(); while(!isdigit(c)){ if(c=='-')w=-1; c=getchar(); } while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar(); return x*w; } const int maxn=105*2; int a[maxn],sum[maxn],d[maxn][maxn],d2[maxn][maxn]; int main() { int n=read(); for(int i=1;i<=n;i++)a[i]=a[i+n]=read(); for(int i=1;i<=(n+n);i++)sum[i]=sum[i-1]+a[i];//前缀和 for(int len=2;len<=n;len++) for(int i=1,j=i+len-1;i<n+n and j<n+n ;i++,j=i+len-1) { d[i][j]=INF; for(int k=i;k<j;k++) { if(d[i][j]>d[i][k]+d[k+1][j]+sum[j]-sum[i-1]) d[i][j]=d[i][k]+d[k+1][j]+sum[j]-sum[i-1]; if(d2[i][j]<d2[i][k]+d2[k+1][j]+sum[j]-sum[i-1]) d2[i][j]=d2[i][k]+d2[k+1][j]+sum[j]-sum[i-1]; } } int ans1=INF,ans2=0; for(int i=1;i<=n;i++)ans1=min(ans1,d[i][i+n-1]),ans2=max(ans2,d2[i][i+n-1]); printf("%d\n%d\n",ans1,ans2); return 0; }
当然,这个直接把n<<1的作死做法是没有办法干过大多数题目的。于是我们就需要对dp进行平行四边形优化
但是我没学……以后学了单独写一篇题解吧。
扩展:这道题的数据范围是n<=100,而我们给它还扩充到了n<=200。那么如果n更大呢?比如n<=40000?
这里有一道题目洛谷P5569
是的我们没法再用40000*40000的dp做了。
我也不会
这已经不是dp的问题了!但是还是给大佬们一个传送门
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现