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 }

 

posted @ 2020-03-18 17:05  古比  阅读(207)  评论(0编辑  收藏  举报