套路区间DP题
先跟[NOI2001合并石子]一样,复制一下序列,断环成链。
然后设\(dp[i,j,k]\)为将区间\([i,j]\)分成\(k\)个部分相乘的最优解,可以得出如下状态转移方程
\[dp[i,j,k]=\max_{i+k-2≤g<r} \{dp[i,g,k-1]·sum[g+1,j]\}\]
\(sum?\)用前缀和来维护,注意一下\(Mod?\)运算和取余运算不同,如果为负数则需要变成正数。
#include <bits/stdc++.h>
#define Mod(x) (x=((x%mod)+mod)%mod)
const int max_n=50+5;
const int max_m=10+5;
const int mod=10;
const int inf=0x3f3f3f3f;
int N,M,Ans1=inf,Ans2;
int dp[2][max_m][max_n][max_n],sum[max_n<<1];
inline int read()
{
register int x=0,v=1;
register char ch=getchar();
while(!isdigit(ch))
{
if(ch==‘-‘) v=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-‘0‘;
ch=getchar();
}
return x*v;
}
int main()
{
int t;
N=read(),M=read();
for(int i=1;i<=N;++i)
sum[i]=sum[i+N]=read();
for(int i=1;i<=N<<1;++i)
sum[i]+=sum[i-1];
for(int i=1;i<=N;++i)
for(int j=i;j<=i+N-1;++j)
dp[0][1][i][j]=dp[1][1][i][j]=sum[j]-sum[i-1],Mod(dp[0][1][i][j]),Mod(dp[1][1][i][j]);
for(int i=2;i<=M;++i)
{
for(int l=1;l<=N;++l)
{
for(int r=l+i-1;r<=l+N-1;++r)
{
dp[0][i][l][r]=inf;
for(int k=l+i-2;k<r;++k)
{
t=sum[r]-sum[k],Mod(t);
dp[0][i][l][r]=std::min(dp[0][i][l][r],dp[0][i-1][l][k]*t);
dp[1][i][l][r]=std::max(dp[1][i][l][r],dp[1][i-1][l][k]*t);
}
}
}
}
for(int i=1;i<=N;++i)
Ans1=std::min(Ans1,dp[0][M][i][i+N-1]),Ans2=std::max(Ans2,dp[1][M][i][i+N-1]);
printf("%d\n%d\n",Ans1,Ans2);
return 0;
}