DP——数字游戏
Description
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。 例如,对于下面这圈数字(n=4,m=2):
![](http://10.11.246.150/JudgeOnline/topimages/2555.gif)
![](http://10.11.246.150/JudgeOnline/topimages/2555.gif)
当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。 丁丁请你编写程序帮他赢得这个游戏。
Input
多个测试案例,处理到文件末尾,每个测试 第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。
Output
每个测试案例输出 有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。
Sample Input
4 2 4 3 -1 2
Sample Output
7 81
HINT
大意:经典DP
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int inf = 43333; const int MAX = 100; int dp1[MAX][MAX],dp2[MAX][MAX],sum[MAX]; int n,m; int min1,max1; int DP(int *a) { for(int i = 1 ; i <= n; i++) sum[i] = sum[i-1] + a[i]; for(int i = 0; i <= n ;i++){ for(int j = 0; j <= m ;j++){ dp1[i][j] = 0; dp2[i][j] = inf; } } dp1[0][0] = dp2[0][0] = 1; for(int i = 1 ; i <= n ;i++) dp1[i][1] = dp2[i][1] = (sum[i]%10+10)%10; for(int j = 2; j <= m ;j++){ for(int k = j; k <= n ;k++){ for(int p = j-1; p < k; p++){ dp1[k][j] = max(dp1[k][j],dp1[p][j-1]*(((sum[k]-sum[p])%10+10)%10)); dp2[k][j] = min(dp2[k][j],dp2[p][j-1]*(((sum[k]-sum[p])%10+10)%10)); } } } max1 = max(max1,dp1[n][m]); min1 = min(min1,dp2[n][m]); } int main() { int a[120]; while(~scanf("%d%d",&n,&m)){ min1 = inf; max1= 0; memset(sum,0,sizeof(sum)); for(int i = 1 ; i <= n ;i++){ scanf("%d",a+i); a[i+n] = a[i]; } for(int i = 0 ; i < n;i++) DP(a+i); printf("%d\n%d\n",min1,max1); } return 0; }