2013-01-27 08:57:54Morris

[ZJ][高精度DP] d870. NOIP2000 3.乘积最大

內容 :

今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目: 设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。 同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 有一个数字串:312 N=3K=1时会有以下两种分法: 1)  3*12=362)  31*2=62      这时,符合题目要求的结果是:31*2=62    现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

輸入說明 :

   程序的输入共有两行:   第一行共有2个自然数NK6N401K6   第二行是一个长度为N的数字串。

輸出說明 :

   结果显示在屏幕上,相对于输入,应输出所求得的最大乘积(一个自然数)。

範例輸入 :

4 2
1231

範例輸出 :

62

提示 :

出處 :

NOIP2000普及组第三题、提高组第二题 (管理:liouzhou_101)

DP[劃分到哪一個位置][分成幾個數字] = 最大值


/**********************************************************************************/
/*  Problem: d870 "NOIP2000 3.乘积最大" from NOIP2000普及组第三题、提高组第二题*/
/*  Language: CPP (1725 Bytes)                                                    */
/*  Result: AC(5ms, 435KB) judge by this@ZeroJudge                                */
/*  Author: morris1028 at 2013-01-26 16:50:35                                     */
/**********************************************************************************/


#include <stdio.h>

void multiply(int a[], int b[], int c[]) {
    int i, j, k;
    for(i = 0; i < 100; i++)
        for(j = 0; j < 100; j++)
            if(i+j < 100)
                c[i+j] += a[i]*b[j];
    for(i = 0; i < 100; i++)
        if(c[i] >= 10)
            c[i+1] += c[i]/10, c[i] %= 10;
}
int compare(int a[], int b[]) {
    int i;
    for(i = 99; i >= 0; i--)
        if(a[i] > b[i])
            return 1;
        else if(a[i] < b[i])
            return 0;
    return 1;
}
void assign(int a[], int b[]) {
    int i;
    for(i = 0; i < 100; i++)
        a[i] = b[i];
}
void print(int a[]) {
    int i = 99;
    while(i >= 1 && a[i] == 0)  i--;
    while(i >= 0)   putchar(a[i]+'0'), i--;
}
int main() {
    int N, K, i, j, k, ti, tj;
    char s[50];
    scanf("%d %d", &N, &K);
    scanf("%s", s+1);
    K++;
    for(i = 1; i <= N; i++)
        s[i] -= '0';
    int dp[50][10][100] = {};
    dp[0][0][0] = 1;
    for(i = 1; i <= N; i++) {
        for(j = 0; j < K; j++) {
            for(k = i; k <= N; k++) {
                //dp[k][j+1] = dp[i-1][j]*num[i~>k];
                int tmp[100] = {}, num[100] = {};
                for(ti = 0, tj = k; tj >= i; ti++, tj--)
                    num[ti] = s[tj];
                multiply(dp[i-1][j], num, tmp); // tmp = dp[i-1][j]*num
                /*printf("[%d %d] %d\n", k, j+1, i);
                print(dp[i-1][j]);
                printf(" * "), print(num), printf(" = "), print(tmp);
                puts("\n ========== ");*/
                if(!compare(dp[k][j+1], tmp))
                    assign(dp[k][j+1], tmp);
            }
        }
    }
    print(dp[N][K]);
    puts("");
    return 0;
}