2021-04-24

acm每周总结

这个星期我们学习了区间dp,通过本周学习我总结一下,这种题型的解题思路。
1.区间长度定义
2.定左端点(通过左端点定右端点)
3.在子区间里寻找分界点并考虑区间dp动态方程,说实话(我认为只要把例子中从区间长度为三推到四,基本上就可以大致推出dp动态规划方程)
4.base case(这个也很重要,好的初始设置是成功解题的关键,可以省很多事)

原始代码

base case
dp[][]=
for(int len=;len<=n;len++)
{for(int r=1,l=len;l<n;l++,r++)
{for(int k=r;k<l;k++)
{dp方程;}}}

例题vjq

一条直线上有n个石子,两两合并问,所合并的最大和最小值。
Sample Input
3
1 2 3
Sample Output
9 11
解题思路
1.根据区间dp思路思考
dp方程
dp1[l][r]=max(dp1[l][r],dp1[l][k]+dp1[k+1][r]+sum[r]-sum[l-1]);
dp2[l][r]=min(dp2[l][r],dp2[l][k]+dp2[k+1][r]+sum[r]-sum[l-1])
即每次和
dp[l][r]=max/min(dp[l][r],dp[l][k]+dp1[k+1][r]+合并花费值);
合并花费值只需将左端点的总花费减右端点即可
2.base case的确定
memset(dp2,0x3f3f3f3f3f,sizeof(dp2));
memset(dp1,0,sizeof(dp1));
memset(sum,0,sizeof(sum));
r=l时dp[r][l]=0
代码实现
#include
#include
#include
using namespace std;
long long a[105],sum[105],f1[105][105],f2[105][105];
int n;
int main()
{
while(cin>>n)
{memset(f2,0x3f3f3f3f3f,sizeof(f2));
memset(f1,0,sizeof(f1));
memset(sum,0,sizeof(sum));
for(int q=1;q<=n;q++)
{cin>>a[q];
sum[q]=sum[q-1]+a[q];
f2[q][q]=0;
f1[q][q]=0;
}
for(int q=1;q<n;q++)
{for(int w=1;w<=n-q;w++)
{int r=w+q;
for(int e=w;e<r;e++)
{f1[w][r]=max(f1[w][r],f1[w][e]+f1[e+1][r]+sum[r]-sum[w-1]);
f2[w][r]=min(f2[w][r],f2[w][e]+f2[e+1][r]+sum[r]-sum[w-1]);}}
}
long long maxx=f1[1][n];
long long minn=f2[1][n];
cout<<minn<<" "<<maxx<<endl;
}
return 0;
}

环形问题思路

这是本周遇到的一个典型的问题只需在
数组输出时在后将数在遍历一遍即可,并考虑在直线基础上区间取值的改动

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值