递推的本质是从小到大,所以区间dp是从小区间到大区间

题目描述
链接:https://ac.nowcoder.com/acm/problem/51170
来源:牛客网

解析和代码
f[i][j] //子问题是i到j区间的最小的代价
#include<bits/stdc++.h>
using namespace std;
int n;
int a[305];
int f[305][305];
int main(){
cin >> n;
for(int i=1;i<=n;++i){
cin >> a[i];
a[i]+=a[i-1];
}
memset(f,0x3f,sizeof(f));
//f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+a[j]-a[i-1]);
//动态规划意思是找到一个方程,然后可以从小一直推大,直到可知题目所求
//而究竟是什么状态从小到大,此题的状态如标题是区间,准确来说是这个区间合并的最小代价
//所以边界取决于从小到大的小
//以下两行:j表示区间右边界,i表示区间左边界,这样循环就能保证区间是从小区间到大区间的
for(int j=1;j<=n;++j){
for(int i=j;i>=1;--i){
if(i>=j) f[i][j]=0; //因为f数组初始化为了无穷大,所以边界要手动定义为0
for(int k=i;k<j;++k){
//以下注释是废话,不用看(打了那么多字舍不得删而已)
//k不能等于j,否则:会在转移方程转移时出现k比j大的情况,例如f[2][1];并且会在区间长度为2时,进来2次,从而加了上一次的f[i][j],例如 i=1,j=2时,k会等于1(第一次进来) ,f[1][2]=f[1][1]+f[2][2]+... ,第二次进来k=2,f[1][2]=f[1,2]+f[2,2]+...。
//当然这是求最小值,所以等不等于没关系(其实求最大值也没关系),但还是规范一下自己的代码比较好
f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+a[j]-a[i-1]);
}
}
}
cout << f[1][n];
return 0;
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-01 10:56
点赞 评论 收藏
分享
程序员牛肉:主要是因为小厂的资金本来就很吃紧,所以更喜欢有实习经历的同学。来了就能上手。 而大厂因为钱多,实习生一天三四百的就不算事。所以愿意培养你,在面试的时候也就不在乎你有没有实习(除非是同级别大厂的实习。) 按照你的简历来看,同质化太严重了。项目也很烂大街。 要么换项目,要么考研。 你现在选择工作的话,前景不是很好了。
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-27 20:15
还能挽救吗?找同学帮忙看了一下&nbsp;字节怎么能如此对我
牛客26396789...:你这是严重红线,被发现你自己永远进不去,你那个同学直接走人,你还敢宣扬
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务