Vijos P1218 数字游戏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 数字游戏的主要内容,如果未能解决你的问题,请参考以下文章

dfs(vijos113424点游戏)

P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib

P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib (数论—素数 + DFS)

Vijos 1193 扫雷 动态规划

洛谷P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib

LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段