首页 > 代码库 > 洛谷P1043 数字游戏

洛谷P1043 数字游戏

题意将n个数排位环状,将其分为 k个部分,k个部分 对 10 取模 然后累乘起来,求其最大和最小的值

动态规划 
用 f[ i ][ j ][ k ] 表示将 i--j这几个数 分为 k个部分 能够取到的最大值 
可知状态转移方程 f[ i ][ j ][ k ] = max(f[ i ][ j ][ k ],f[ i ][ l-1 ][ k-1 ] + c[ j ] - c[l-1] 
c 表示前缀和 我们化圈为线 将他的两倍记录下来就行了

 

 

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iomanip>
#include <iostream>
using namespace std ;

int n,m ; 
int f[102][102][10],f2[102][102][10],s[102],c[102] ;

int main() 
{
    scanf("%d%d",&n,&m) ;
    for(int i=1;i<=n;i++) scanf("%d",&s[ i ]),s[n+i] = s[ i ] ;
    for(int i=1;i<=2*n;i++) c[i] = c[i-1]+s[i] ;
    for(int i=1;i<=2*n;i++) 
        for(int j=i;j<=2*n;j++)
        for(int k=1;k<=m;k++) 
        {
            if(k<2) 
            {
                f[i][j][k] = ( (f[i][j-1][k] +s[j] ) %10+10) %10 ;
                f2[i][j][k] = ((f2[i][j-1][k]+s[j])  %10+10) %10 ; 
            }    
            else f[i][j][k] = 1e9 ;
        }    
    for(int i=2;i<=m;i++) 
        for(int j=1;j<=2*n;j++) 
          for(int k=i+j-1;k<=2*n;k++) 
            for(int l=i+j-1;l<=k;l++) 
            {
                f[j][k][i] = min(f[j][k][i],f[j][l-1][i-1] *(((c[k]-c[l-1])%10+10)%10) ) ;
                f2[j][k][i] = max(f2[j][k][i],f2[j][l-1][i-1]*(((c[k]-c[l-1])%10+10)%10 ) );
            }
    int mi = 1e9 ;
    int ma = 0 ;
    for(int i=1;i<=n;i++) 
    {
        mi = min(mi,f[i][i+n-1][m]) ;
        ma = max(ma,f2[i][i+n-1][m]) ;
    }
    printf("%d\n%d",mi,ma) ;
    
    return 0 ;
}

洛谷P1043 数字游戏