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 的提升,只能说,好提