洛谷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
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 (m2*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;
}

  

你可能感兴趣的:(洛谷P1043 数字游戏---区间dp)