算法训练 乘积最大

ALGO-17 乘积最大

@蓝桥杯 练习系统 ALGO-17
@洛谷 P1018
资源限制

时间限制:1.0s 内存限制:256.0MB

问题描述

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

输入格式

程序的输入共有两行:
第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)
第二行是一个长度为N的数字串。

输出格式

输出所求得的最大乘积(一个自然数)。

测试样例

输入:
4 2
1231

输出:
62

数据规模与约定

蓝桥:
对于20%的数据,n <= 5000。
对于100%的数据,1 <= n <= 200000,0 <= a[i]<2^31。

洛谷:
6 ≤ N ≤ 40, 1 ≤ K ≤ 6

AC code (蓝桥)

public class Main {

    public static void main(String[] args) {
        InputReader in = new InputReader();
        int N = in.nextInt(), K = in.nextInt();
        int[] num = new int[N], dp[] = new int[N][K + 1];
        for (int i = 0; i < N; i++) num[i] = in.nextByte() & 0x0F;
        for (int i = 0, l = N - K, temp = 0; i < l; i++) dp[i][0] = temp = temp * 10 + num[i];
        for (int i = 1; i < N; i++)
            for (int j = 1; j <= K; j++)
                for (int l = 0, temp = 0; l < i; l++, temp = 0){
                    for (int k = l + 1; k <= i; k++) temp = temp * 10 + num[k];
                    dp[i][j] = Math.max(dp[i][j], dp[l][j - 1] * temp);
                }
        System.out.print(dp[N - 1][K]);
    }

    static class InputReader {

        byte[] inBuff;
        int inLen;
        int lenBuff;

        InputReader() { this(1024); }

        InputReader(int size) {
            this.inBuff = new byte[size];
            inLen = lenBuff = 0;
        }

        int nextByte() {
            if (inLen <= lenBuff)
                try {
                    inLen = System.in.read(inBuff);
                    lenBuff = 0;
                } catch (java.io.IOException e) {
                    e.printStackTrace();
                }
            return inBuff[lenBuff++];
        }

        String next() {
            StringBuilder res = new StringBuilder();
            int b;
            while ((b = nextByte()) > 32) res.appendCodePoint(b);
            return res.toString();
        }

        int nextInt() { return Integer.parseInt(next()); }
    }
}

AC code (洛谷)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        int n = in.nextInt(), k = in.nextInt() + 1, dps = n * k;
        int[] tuple = new int[n];
        BigInt[] dp = new BigInt[dps];
        for (int i = 0; i < dps; i++) dp[i] = new BigInt();
        String nums = in.next();
        for (int i = 0, j = n - 1, l = 0; i < n; l = ++i * k, j--) {
            tuple[i] = nums.charAt(j) & 0xf;
            dp[l] = new BigInt(tuple, j, i);
        }
        for (int i = 1; i < n; i++)
            for (int j = 1; j < k; j++) {
                for (int l = 0; l < i; l++){
                    BigInt temp = new BigInt(tuple, n - i - 1, i - l - 1);
                    dp[i * k + j] = BigInt.max(dp[i * k + j], BigInt.mul(dp[l * k + j - 1], temp));
                }
            }
        System.out.println(dp[dps - 1]);
    }

    static class BigInt {

        int value[], start, len;

        BigInt() { this(new int[1], 0, 0);}

        BigInt(BigInt n) {
            int[] value = new int[n.len + 1];
            System.arraycopy(n.value, n.start, value, 0, n.len + 1);
            this.value = value;
            this.len = n.len;
            this.start = 0;
        }

        BigInt(int[] value, int start, int len) {
            this.value = value;
            this.start = start;
            this.len = len;
        }

        public static BigInt max(BigInt var1, BigInt var2) {
            if (var1.len > var2.len) return new BigInt(var1);
            if (var1.len < var2.len) return new BigInt(var2);
            for (int i = var1.len; i >= 0; i--) {
                if (var1.value[i + var1.start] > var2.value[i + var2.start]) return new BigInt(var1);
                if (var1.value[i + var1.start] < var2.value[i + var2.start]) return new BigInt(var2);
            }
            return new BigInt(var1);
        }

        public static BigInt mul(BigInt var1, BigInt var2) {
            int var3 = var1.len;
            int var4 = var2.len;
            int value[] = new int[var3 + var4 + 2];
            int last = 0;
            for (int i = 0; i <= var3; i++)
                for (int j = 0; j <= var4; j++) value[i + j] += var1.value[i + var1.start] * var2.value[j + var2.start];
            for (int i = 0; i < value.length; i++) {
                if (value[i] >= 10) {
                    value[i + 1] += value[i] / 10;
                    value[i] %= 10;
                }
                if (value[i] != 0) last = i;
            }
            return new BigInt(value, 0, last);
        }

        public String toString() {
            StringBuilder res = new StringBuilder();
            for (int i = len; i >= 0; i--) res.append(value[i + start]);
            return res.toString();
        }
    }

    static class InputReader {

        BufferedReader read;
        StringTokenizer tok;
        String delimiters;

        InputReader(InputStream in) { this(in, " \n\t\r\f"); }

        InputReader(InputStream in, String delimiters) {
            this.read = new BufferedReader(new InputStreamReader(in));
            this.tok = new StringTokenizer("", this.delimiters = delimiters);
        }

        String next() {
            while (!tok.hasMoreTokens())
                try {
                    tok = new StringTokenizer(read.readLine(), delimiters);
                } catch (IOException e) { }
            return tok.nextToken();
        }

        int nextInt() { return Integer.parseInt(next(), 10); }
    }
}

为什么这么写

Java麻烦的就是没有结构体,而对象数组又不会自己初始化,当然大部分的动态规划题都可以靠初始化第一层,然后判 null 来解决,不过我不喜欢这样,于是尝试了更加不明所以的写法

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        int n = in.nextInt(), k = in.nextInt() + 1, dps = n * k;
        int[] tuple = new int[n];
        int[] dp[] = new int[dps][1], dpl = new int[dps], dpo = new int[dps];
        String nums = in.next();
        for (int i = 0, j = n - 1, l = 0; i < n; l = ++i * k, j--) {
            dpl[l] = i;
            tuple[i] = nums.charAt(j) & 0xf;
            dpo[l] = j;
            dp[l] = tuple;
        }
        for (int i = 1, ik = k; i < n; i++, ik += k)
            for (int j = 1; j < k; j++) {
                dpa: for (int l = 0; l < i; l++){
                    int ucur = l * k + j - 1, uval[] = dp[ucur], ulen = dpl[ucur], uoff = dpo[ucur], tlen = i - l, toff = n - i - 1,
                        value[] = new int[ulen + tlen + 1], vlen = 0;
                    for (int p = 0; p <= ulen; p++)
                        for (int q = 0; q < tlen; q++) value[p + q] += uval[p + uoff] * tuple[q + toff];
                    for (int p = 0, q = value.length; p < q; p++) {
                        if (value[p] >= 10) {
                            value[p + 1] += value[p] / 10;
                            value[p] %= 10;
                        }
                        if (value[p] != 0) vlen = p;
                    }
                    int cur = ik + j;
                    if (dpl[cur] > vlen) continue;
                    else if (dpl[cur] == vlen) {
                        int cval[] = dp[cur], coff = dpo[cur];
                        for (int p = vlen; p >= 0; p--)
                            if (cval[p + coff] == value[p]) continue;
                            else if (cval[p + coff] < value[p])break;
                            else continue dpa;
                    }
                    dp[cur] = value;
                    dpl[cur] = vlen;
                    dpo[cur] = 0;
                }
            }
        StringBuilder out = new StringBuilder();
        for (int cur = dps - 1, i = dpl[cur], j = dpo[cur], v[] = dp[cur]; i >= 0; i--) out.append(v[i + j]);
        System.out.print(out);
    }

    static class InputReader {

        BufferedReader read;
        StringTokenizer tok;
        String delimiters;

        InputReader(InputStream in) { this(in, " \n\t\r\f"); }

        InputReader(InputStream in, String delimiters) {
            this.read = new BufferedReader(new InputStreamReader(in));
            this.tok = new StringTokenizer("", this.delimiters = delimiters);
        }

        String next() {
            while (!tok.hasMoreTokens())
                try {
                    tok = new StringTokenizer(read.readLine(), delimiters);
                } catch (IOException e) { }
            return tok.nextToken();
        }

        int nextInt() { return Integer.parseInt(next(), 10); }
    }
}

获得了 20 m s 20ms 20ms 的提升,只能说,好提

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值