zoukankan      html  css  js  c++  java
  • codevs1085数字游戏(环形DP+划分DP )

    1085 数字游戏

     
     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
     
    题目描述 Description

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

    例如,对于下面这圈数字(n=4,m=2):

                                      2

                       4                           -1

                                     3

    当要求最小值时,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值时,为((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特别值得注意的是,无论是负数还是正数,对10取模的结果均为非负值。

    丁丁请你编写程序帮他赢得这个游戏。

    输入描述 Input Description

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

    输出描述 Output Description

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

    样例输入 Sample Input

    4 2

    4

    3

    -1

    2

    样例输出 Sample Output

    7

    81

    /*
    这道题是典型的环形DP+划分DP 
    我们设f[i][j]为前i个数分成j份得到的最大值
    g[i][j]表示前i个数分成j份获得的最小值。
    于是状态转移方程很容易推出来:f[i][j]=max(f[i][j],f[k][j-1]*(((sum[i]-sum[k])%10+10)%10));
    我们枚举一个k端点在1~i-1之间
    表示这k个数分成j-1份之后剩下的k+1到i分成一份
    所获得的价值用前缀和处理即可。
    注意环的处理。
    */
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    int n,m,Max,Min;
    int sum[201],f[200][20],g[200][20],num[201];
    
    void 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++)
            {
                f[i][j]=0;
                g[i][j]=999999999;
            }
        for(int i=1;i<=n;i++)
          f[i][1]=g[i][1]=(sum[i]%10+10)%10;
        for(int j=2;j<=m;j++)
          for(int i=j;i<=n;i++)
            for(int k=j-1;k<=i-1;k++)
              {
                  f[i][j]=max(f[i][j],f[k][j-1]*(((sum[i]-sum[k])%10+10)%10));
                  g[i][j]=min(g[i][j],g[k][j-1]*(((sum[i]-sum[k])%10+10)%10));
              }
        Max=max(Max,f[n][m]);   
        Min=min(Min,g[n][m]);  
    }
    
    int main()
    {
        Max=0;
        Min=999999999;
        scanf("%d%d",&n,&m);
        for (int i=1; i<=n; i++)
        {
            scanf("%d",&num[i]);
            num[i+n]=num[i];    
        }
        for (int i=0; i<n; i++) dp(num+i); 
        printf("%d
    %d
    ",Min,Max);
        return 0;
    }
    心若向阳,无言悲伤
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    Error updating database. Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction(mysql 事务方法debug后果)
    按钮防止多次点击重复提交的方法
    图解为什么要使用线程池?
    如果屏蔽父容器的CSS样式。
    一个JSON解构赋值给另一个字段不同的JSON
    @Transactional的参数意义及使用。spring中事务注解的配置情况
    var me = this的实际意义,js将this引用赋值的意义
    EasyUI Combobox 组合框在后端数据初始化后前端的数据加工处理
    >>和>>>的效率分析
    js中debug的使用
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6351815.html
Copyright © 2011-2022 走看看