1.区间动归 dp 化圆为线 前缀和
ybt
通过
测试点 | 结果 | 内存 | 时间 |
测试点1 | 答案正确 | 848KB | 2MS |
测试点2 | 答案正确 | 644KB | 2MS |
测试点3 | 答案正确 | 656KB | 2MS |
测试点4 | 答案正确 | 656KB | 1MS |
测试点5 | 答案正确 | 800KB | 2MS |
测试点6 | 答案正确 | 632KB | 1MS |
测试点7 | 答案正确 | 660KB | 1MS |
测试点8 | 答案正确 | 652KB | 1MS |
测试点9 | 答案正确 | 1168KB | 3MS |
测试点10 | 答案正确 | 656KB | 1MS |
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)
普及+/提高 习得什么?区间动规的基本实现细节吧。