首页 > 代码库 > Vijos P1218 数字游戏

Vijos P1218 数字游戏

描述

丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。

格式

输入格式

输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于10^410?4??,按顺序给出圈中的数字,首尾相接。

输出格式

输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。

样例1

样例输入1

4 2
4
3
-1
2

样例输出1

7
81

限制

各个测试点1s

提示

DP!^_^

 

【分析】

典型的区间dp,明明是普及组第二题还调了半天...果然还是熟练度的问题。

 

【代码】

 1 #include <bits/stdc++.h>
 2 #define fo(i, j, k) for(int i=j;i<=k;++i)
 3 using namespace std;
 4 
 5 long long ans, n, m, a[51], b[51], dp[10][105][105];
 6 
 7 void init() {
 8     cin >> n >> m;
 9     for (int i=1;i<=n;++i){
10         cin >> a[i];
11         b[i]=b[i-1]+a[i];
12     }
13     fo(i, n+1, 2*n-1)
14         b[i]=b[i-1]+a[i-n];
15 }
16 
17 void DP1()
18 {
19     ans=0x7fffffff;
20     for (int i=0;i<=m;++i)
21         for (int j=0;j<=2*n;++j)
22             for (int k=0;k<=2*n;++k)
23                 dp[i][j][k]=0x7fffffff;
24     for (int k=1;k<=m;++k)
25         for (int i=1;i<2*n;++i)
26             for (int t=1;t<=n;++t) {
27                 int j=i+t-1;
28                 if (j>2*n-1)
29                     break;
30                 if (k==1){
31                     dp[k][i][j]=((b[j]-b[i-1])%10+10)%10;
32                 }
33                 else {
34                     for (int q=i;q<j;++q){
35                         dp[k][i][j]=min(dp[k][i][j], dp[1][i][q]*dp[k-1][q+1][j]);
36                     }
37                 }
38             }
39     for (int i=1;i<=n;++i){
40         ans=min(ans, dp[m][i][i+n-1]);
41     }
42     cout << ans << endl;
43 }
44 
45 void DP2()
46 {
47     ans=-0x7fffffff;
48     for (int i=0;i<=m;++i)
49         for (int j=0;j<=2*n;++j)
50             for (int k=0;k<=2*n;++k)
51                 dp[i][j][k]=-0x7fffffff;
52     for (int k=1;k<=m;++k)
53         for (int i=1;i<=n;++i)
54             for (int t=1;t<=n;++t) {
55                 int j=i+t-1;
56                 if (j>2*n-1)
57                     break;
58                 if (k==1)
59                     dp[k][i][j]=((b[j]-b[i-1])%10+10)%10;
60                 else {
61                     for (int q=i;q<j;++q) {
62                         dp[k][i][j]=max(dp[k][i][j], dp[1][i][q]*dp[k-1][q+1][j]);
63                     }
64                 }
65             }
66     for (int i=1;i<=n;++i)
67         ans=max(ans, dp[m][i][i+n-1]);
68     cout << ans << endl;
69 }
70 
71 int main()
72 {
73     init();
74     DP1();
75     DP2();
76 }

 

Vijos P1218 数字游戏