洛谷P1043 数字游戏---区间dp
题目链接:https://www.luogu.com.cn/problem/P1043
简单题意:将n个数(环形)分成k份,每份内求和对10取模,求各份相乘后的最大值和最小值
设f[i][j][l]表示将i到j分成l份的最大(小)值,则有f[i][j][l]=max(min)(f[i][j][l],f[i][t][l-1]*sum(t+1,j))。一个技巧就是把环复制一倍变成链,这个技巧在能量项链遇到过,poj1179好像也用到了(虽然还木有做),还是挺常见的技巧。注意把l=1的情况初始化,还有c++默认负数取模的问题,要用((x%mod)+mod)%mod将结果变成正数
#include<bits/stdc++.h>
using namespace std;
int n,i,j,k,l,m,t,ans1,ans2;
int a[110],s[110],f1[110][110][15],f2[110][110][15];
int sum(int p,int q){ return ((s[q]-s[p-1])%10+10)%10;}
int main(){
scanf("%d%d",&n,&k);
for (i=1;i<=n;i++) scanf("%d",&a[i]);
for (i=n+1;i<=2*n-1;i++) a[i]=a[i-n];
for (i=1;i<=2*n-1;i++) s[i]=s[i-1]+a[i];
for (m=0;m<=n;m++)
for (i=1;i<=2*n-1;i++){
j=i+m;
if (j<=2*n-1) f1[i][j][1]=f2[i][j][1]=sum(i,j);
}
for (l=2;l<=k;l++)
for (m=1;m<=n;m++){
if (m<k-1) continue;
for (i=1;i<=2*n-1;i++){
int j=i+m;
if (j>2*n-1) continue;
f1[i][j][l]=1e9;f2[i][j][l]=0;
for (t=i;t<=j-1;t++)
if (t-i+1>=l-1){
f1[i][j][l]=min(f1[i][j][l],f1[i][t][l-1]*sum(t+1,j));
f2[i][j][l]=max(f2[i][j][l],f2[i][t][l-1]*sum(t+1,j));
}
}
}
ans1=1e9;ans2=0;
for (i=1;i<=n;i++){
ans1=min(ans1,f1[i][i+n-1][k]); ans2=max(ans2,f2[i][i+n-1][k]);
}
printf("%d\n%d\n",ans1,ans2);
return 0;
}

浙公网安备 33010602011771号