1569 例题1 石子合并(LOJ10147 LUOGU1880 普及+/提高) 区间动归 dp 化圆为线 前缀和

这篇博客详细介绍了区间动归DP的原理,并通过一个具体的例子展示了如何将圆状问题转化为线性问题求解。文章提供了代码实现,包括前缀和的计算,以及在不同区间长度下的动态规划更新。最后,博客讨论了算法的时间复杂度和应用范围,适合初学者理解区间动规的基本实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总目录

在线测评地址(ybt)

在线测评地址(LOJ)

在线测评地址(LUOGU)

1.区间动归 dp 化圆为线 前缀和

ybt

通过

测试点结果内存时间
测试点1答案正确848KB2MS
测试点2答案正确644KB2MS
测试点3答案正确656KB2MS
测试点4答案正确656KB1MS
测试点5答案正确800KB2MS
测试点6答案正确632KB1MS
测试点7答案正确660KB1MS
测试点8答案正确652KB1MS
测试点9答案正确1168KB3MS
测试点10答案正确656KB1MS

LOJ

LUOGU

 

样例模拟如下:

4
4 5 9 4

最小得分43计算过程如下:

因为是圈,故将1串变成2串处理。
位置1 2 3 4 5 6 7 8
数值4 5 9 4 4 5 9 4

a[1]=4,a[2]=5,a[3]=9,a[4]=4,a[5]=4,a[6]=5,a[7]=9,a[8]=4

dp[1][2]=a[1]+a[2]=4+5=9
dp[2][3]=a[2]+a[3]=5+9=14
d[3][4]=a[3]+a[4]=9+4=13
dp[4][5]=a[4]+a[5]=4+4=8
dp[5][6]=a[5]+a[6]=4+5=9
dp[6][7]=a[6]+a[7]=5+9=14
dp[7][8]=a[7]+a[8]=9+4=13

dp[1][3]=min(dp[1][2],dp[2][3])+(a[1]+a[2]+a[3])=min(9,14)+18=27
dp[2][4]=min(dp[2][3],dp[3][4])+(a[2]+a[3]+a[4])=min(14,13)+18=31
dp[3][5]=min(dp[3][4],dp[4][5])+(a[3]+a[4]+a[5])=min(13,8)+17=25
dp[4][6]=min(dp[4][5],dp[5][6])+(a[4]+a[5]+a[6])=min(8,9)+13=21
dp[5][7]=min(dp[5][6],dp[6][7])+(a[5]+a[6]+a[7])=min(9,14)+18=27
dp[6][8]=min(dp[6][7],dp[7][8])+(a[6]+a[7]+a[8])=min(14,13)+18=31

dp[1][4]=min(dp[1][2]+dp[3][4],dp[1][3],dp[2][4])+(a[1]+a[2]+a[3]+a[4])=min(22,27,31)+22=44
dp[2][5]=min(dp[2][3]+dp[4][5],dp[2][4],dp[3][5])+(a[2]+a[3]+a[4]+a[5])=min(22,31,25)+22=44
dp[3][6]=min(dp[3][4]+dp[5][6],dp[3][5],dp[4][6])+(a[3]+a[4]+a[5]+a[6])=min(22,25,21)+22=43
dp[4][7]=min(dp[4][5]+dp[6][7],dp[4][6],dp[5][7])+(a[4]+a[5]+a[6]+a[7])=min(22,21,27)+22=43
dp[5][8]=min(dp[5][6]+dp[7][8],dp[5][7],dp[6][8])+(a[5]+a[6]+a[7]+a[8])=min(22,27,31)+22=44



样例对应的细分区间如下,后来者,或排错有用

lt=1 rt=3; 1 1 2 3
lt=1 rt=3; 1 2 3 3
lt=2 rt=4; 2 2 3 4
lt=2 rt=4; 2 3 4 4
lt=3 rt=5; 3 3 4 5
lt=3 rt=5; 3 4 5 5
lt=4 rt=6; 4 4 5 6
lt=4 rt=6; 4 5 6 6
lt=5 rt=7; 5 5 6 7
lt=5 rt=7; 5 6 7 7
lt=6 rt=8; 6 6 7 8
lt=6 rt=8; 6 7 8 8
lt=1 rt=4; 1 1 2 4
lt=1 rt=4; 1 2 3 4
lt=1 rt=4; 1 3 4 4
lt=2 rt=5; 2 2 3 5
lt=2 rt=5; 2 3 4 5
lt=2 rt=5; 2 4 5 5
lt=3 rt=6; 3 3 4 6
lt=3 rt=6; 3 4 5 6
lt=3 rt=6; 3 5 6 6
lt=4 rt=7; 4 4 5 7
lt=4 rt=7; 4 5 6 7
lt=4 rt=7; 4 6 7 7
lt=5 rt=8; 5 5 6 8
lt=5 rt=8; 5 6 7 8
lt=5 rt=8; 5 7 8 8
43
54

区间动归 dp 化圆为线 前缀和 代码如下:

编程中,最核心的一点,再次细分区间,k取值要从0开始。

#include <bits/stdc++.h>
#define maxn 410
#define INF 2e9
using namespace std;
int a[maxn],dp1[maxn][maxn],sum[maxn],dp2[maxn][maxn];
int main(){
	int n,lt,rt,i,len,mn,k,j,mx;
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i];
	sum[0]=0;
	for(i=1;i<=2*n;i++)sum[i]=sum[i-1]+a[i];
	for(i=1;i<=2*n;i++)
		for(j=i+1;j<=2*n;j++)
			dp1[i][j]=INF; 
	for(i=1;i<2*n;i++)dp2[i][i+1]=dp1[i][i+1]=a[i]+a[i+1];
	for(len=2;len<=n-1;len++) 
		for(lt=1;lt<=2*n;lt++){
			rt=lt+len;
			if(rt>2*n)break;
			for(k=0;k<len;k++){//再细分,请注意k=0(k=1开始不行)开始,不要漏掉每一个细分区间 
				dp1[lt][rt]=min(dp1[lt][rt],dp1[lt][lt+k]+dp1[lt+k+1][rt]+sum[rt]-sum[lt-1]); 
				dp2[lt][rt]=max(dp2[lt][rt],dp2[lt][lt+k]+dp2[lt+k+1][rt]+sum[rt]-sum[lt-1]);
			}
		}
	mn=2e9,mx=0;
	for(i=1;i<=n;i++)
		 if(mn>dp1[i][i+n-1])mn=dp1[i][i+n-1];
	for(i=1;i<=n;i++)
		 if(mx<dp2[i][i+n-1])mx=dp2[i][i+n-1];
	printf("%d\n",mn);
	printf("%d\n",mx);
	return 0;
}

算法的时间复杂度O(n^3)

普及+/提高 习得什么?区间动规的基本实现细节吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值