Vijos_1218_数字游戏_(划分型动态规划+环状动态规划)

描述


https://vijos.org/p/1218

给出n个数围成一个环,将其划分成k个部分,每个部分求和再对10取模,最后将每个部分的值相乘,求其最大值与最小值.

 

描述

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

格式

输入格式

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

输出格式

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

样例1

样例输入1[复制]

4 2
4
3
-1
2

样例输出1[复制]

7
81

限制

各个测试点1s

提示

DP!^_^

 

分析


简单的划分型dp.转移方程:

dp[i][k]=max{dp[j][k-1]*(s[i]-s[j-1])}.

注意:

1.取模.

2.初始化.

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int maxn=50+5,maxk=10+5,INF=0x7fffffff;
 5 
 6 int n,K,ans1,ans2;
 7 int s[maxn<<1];
 8 int dp1[maxn][maxk],dp2[maxn][maxk];
 9 
10 int num(int x){ return((x%10)+10)%10; }
11 void solve(){
12     ans1=INF,ans2=-INF;
13     for(int q=1;q<=n;q++){
14         for(int i=1;i<=n;i++) dp1[i][1]=dp2[i][1]=num(s[q-1+i]-s[q-1]);
15         for(int k=2;k<=K;k++)
16             for(int i=k;i<=n;i++){
17                 dp1[i][k]=INF,dp2[i][k]=-INF;
18                 for(int j=k-1;j<i;j++){
19                     dp1[i][k]=min(dp1[i][k],dp1[j][k-1]*num(s[q-1+i]-s[q-1+j]));
20                     dp2[i][k]=max(dp2[i][k],dp2[j][k-1]*num(s[q-1+i]-s[q-1+j]));
21                 }
22             }
23         ans1=min(ans1,dp1[n][K]);
24         ans2=max(ans2,dp2[n][K]);
25     }
26     printf("%d\n%d\n",ans1,ans2);
27 }
28 void init(){
29     scanf("%d%d",&n,&K);
30     for(int i=1;i<=n;i++){
31         int t; scanf("%d",&t);
32         s[i]=s[i-1]+t;
33     }
34     for(int i=n+1;i<=2*n;i++) s[i]=s[n]+s[i-n];
35 }
36 int main(){
37     init();
38     solve();
39     return 0;
40 }
View Code

 

 

posted @ 2016-05-25 15:01  晴歌。  阅读(609)  评论(0编辑  收藏  举报