P1043 数字游戏(区间dp)
思路:区间题目,首先将环形用两倍数组存,然后初始化区间长度为1的答案,然后用区间即可。
时间复杂度:
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N=105,inf=0x3f3f3f3f;
int a[N][N][10],b[N][N][10],n,m,f[N];//数组a,b分别保存最大值,最小值
int fun(int i,int j){
int x=f[j]-f[i];
return ((x%10)+10)%10;//负数取模.
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&f[i]),f[i+n]=f[i];//将环变成数组储存.
for(int i=1;i<=2*n;i++) f[i]+=f[i-1];
for(int l=1;l<=2*n;l++)
for(int r=l;r<=2*n;r++) a[l][r][1]=b[l][r][1]=fun(l-1,r);//初始化
for(int k=2;k<=m;k++)
for(int i=1;i<=2*n;i++)
for(int j=i+k-1;j<=2*n;j++) b[i][j][k]=inf;//最小值初始化最大.
for(int k=2;k<=m;k++)//区间dp板子
for(int i=1;i<=2*n;i++)
for(int j=i+k-1;j<=2*n;j++)
for(int p=i+k-2;p<j;p++){//分割点.
a[i][j][k]=max(a[i][j][k],a[i][p][k-1]*fun(p,j));
b[i][j][k]=min(b[i][j][k],b[i][p][k-1]*fun(p,j));
}
int mx=0,mn=inf;
for(int i=1;i<=n;i++)//求最值.
mx=max(mx,a[i][i+n-1][m]),mn=min(mn,b[i][i+n-1][m]);
printf("%d\n%d",mn,mx);
return 0;
}