cogs 983. [NOIP2003] 数字游戏

983. [NOIP2003] 数字游戏

★☆   输入文件:numgame.in   输出文件:numgame.out   简单对比
时间限制:1 s   内存限制:128 MB

题目描述

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

当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。

输入格式

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

输出格式

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

【输入样例】
4 2
4
3
-1
2
【输出样例】
7
81
思路:断环成链,记录前缀和。s[i][j][k]表示在区间i-j之间分为k段的最小值,b[i][j][k]表示在区间i-j之间分为k段的最大值。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define oo 2147483647
using namespace std;
int B[101][101][11],S[101][101][11]; 
int n,m; 
int a[101];
int mod(int a){
    return ((a%10)+10)%10;
}
int main(){
    freopen("numgame.in","r",stdin);
    freopen("numgame.out","w",stdout); 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        a[i+n]=a[i];
    }
    for(int i=1;i<=2*n;i++)
        a[i]+=a[i-1];
    for(int l=1;l<=2*n;l++)
        for(int r=l;r<=2*n;r++)
            B[l][r][1]=S[l][r][1]=mod(a[r]-a[l-1]);
    for(int i=2;i<=m;i++)
          for(int l=1;l<=2*n;l++)
            for(int r=l+i-1;r<=2*n;r++)
                  S[l][r][i]=oo;
    for(int i=2;i<=m;i++)
          for(int l=1;l<=2*n;l++)
            for(int r=l+i-1;r<=2*n;r++)
                for(int k=l+i-2;k<r;k++){
                    S[l][r][i]=min(S[l][r][i],S[l][k][i-1]*mod(a[r]-a[k]));
                    B[l][r][i]=max(B[l][r][i],B[l][k][i-1]*mod(a[r]-a[k]));
                  }
    int Max=0,Min=oo;
    for(int i=1;i<=n;i++){
        Max=max(Max,B[i][i+n-1][m]);
        Min=min(Min,S[i][i+n-1][m]);
    }
    printf("%d\n%d",Min,Max);
    return 0;
}

 

 
posted @ 2017-08-26 16:07  一蓑烟雨任生平  阅读(262)  评论(0编辑  收藏  举报