zoukankan      html  css  js  c++  java
  • 1085 数字游戏

    1085 数字游戏

     

    2003年NOIP全国联赛普及组

     时间限制: 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

    数据范围及提示 Data Size & Hint

    en

    划分dp

    把环变链(读入4 3 -1 2变成4 3 -1 2 4 3 -1 2)

    设dp[i][j][k]为把i~j分成k份,各部分内的数字相加,相加所得的k个结果对10取模后再相乘,最终得到的一个数,这个数的最大或最小值。

    dp[i][j][k]=max/min{dp[i][p][k-1]+func(p+1,j)}

    i+k-2<=p<=j-1  func(i,j)=(sum(i,j)%10+10)%10

    (注意有负数取余,这样写:(x%10+10)%10 )

    边界:dp[i][j][1]=func(i,j)

    答案:max/min(dp[i][i+n-1][m])  i=1 to n+1

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    using namespace std;
    #define N 80
    #define ll long long
    ll f[N][N],g[N][N],a[N],s[N],n,m,emax,emin=0x7fffffff;
    ll get(ll x){
        return x>=0?x%10:10-abs(x)%10;
    }
    int main(){
        freopen("sh.txt","r",stdin);
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i],a[i+n]=a[i];
        for(int i=1;i<=n<<1;i++) s[i]=get(s[i-1]+a[i]);
        for(int i=0;i<n;i++){
            memset(f,0,sizeof f);
            memset(g,1,sizeof g);//取较大值 注意数据可能导致上溢 
            for(int j=1;j<=n;j++) f[j][1]=g[j][1]=get(s[j+i]-s[i]);
            for(int j=2;j<=m;j++){
                for(int k=j;k<=n;k++){
                    for(int l=1;l<k;l++){
                        f[k][j]=max(f[k][j],f[l][j-1]*(get(s[k+i]-s[l+i])));
                        g[k][j]=min(g[k][j],g[l][j-1]*(get(s[k+i]-s[l+i])));
                    }
                }
            }
            emax=max(emax,f[n][m]);
            emin=min(emin,g[n][m]);    
        }
        cout<<emin<<endl<<emax<<endl;
        return 0;
    }
  • 相关阅读:
    java JDBC (一)
    java 线程(七)等待与唤醒
    java 线程(六)死锁
    java 线程(五)线程安全 Lock接口
    java 线程(四)线程安全 同步方法
    查询计算机启动了多长时间的工具
    查询计算机启动了多长时间的工具
    百度同步盘无法登陆,报错155010,对策
    百度同步盘无法登陆,报错155010,对策
    锁屏工具,解决三星S7迷你锁屏后不能通过指纹解锁的问题
  • 原文地址:https://www.cnblogs.com/shenben/p/5716024.html
Copyright © 2011-2022 走看看