P1043 数字游戏
https://www.luogu.com.cn/problem/P1043
题意:给出一个圆形区间,区间内有n个数,问分成几段能够让其结果最大;
思路:很明显的区间dp;
首先,因为是圆形区间,所以我们在这n个数后面再补n个数
然后,我们从区间长度由小枚举到大,将分割个数由小枚举到大;最后再枚举一下哪一个区间下是最大值即可;
细节:在枚举分割成几段的时候,区间内的个数不能小于段数
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=120; 4 const int inf=0x3f3f3f3f; 5 int dpmx[maxn][maxn][maxn]; 6 int dpmn[maxn][maxn][maxn]; 7 int a[maxn]; 8 int sum[maxn]; 9 int cal(int x) 10 { 11 return (x%10+10)%10; 12 } 13 int main() 14 { 15 int n,m; 16 cin>>n>>m; 17 for(int i=1;i<=n;i++){ 18 cin>>a[i]; 19 sum[i]=sum[i-1]+a[i]; 20 } 21 for(int i=1;i<=n;i++){ 22 a[i+n]=a[i]; 23 sum[i+n]=sum[i]+sum[n]; 24 } 25 memset(dpmn,127,sizeof(dpmn));//f2记录的是最小值 所以要初始化为极大值 26 for(int i=1;i<=2*n;i++){ 27 for(int j=i;j<=2*n;j++){ 28 dpmn[i][j][1]=dpmx[i][j][1]=cal(sum[j]-sum[i-1]);//预处理每段的值 29 } 30 } 31 for(int l=2;l<=n;l++){//区间长度 32 for(int i=1;i<=n;i++){ 33 int j=i+l-1; 34 for(int h=2;h<=m;h++){//段数 35 for(int k=i+h-1;k<j;k++){ 36 dpmx[i][j][h]=max(dpmx[i][j][h],dpmx[i][k][h-1]*cal(sum[j]-sum[k])); 37 dpmn[i][j][h]=min(dpmn[i][j][h],dpmn[i][k][h-1]*cal(sum[j]-sum[k])); 38 } 39 } 40 } 41 } 42 int mx=0,mn=0x7fffffff; 43 for(int i=1;i<=n;i++){ 44 mx=max(mx,dpmx[i][i+n-1][m]); 45 mn=min(mn,dpmn[i][i+n-1][m]); 46 } 47 cout<<mn<<endl<<mx; 48 }