最大 k 乘积问题 ( 经典区间DP )
题意 : 设 NUM 是一个 n 位十进制整数。如果将 NUM 划分为 k 段,则可得到 k 个整数。这 k 个整数的乘积称为 NUM 的一个 k 乘积。试设计一个算法,对于给定的 NUM 和 k,求出 NUM 的最大 k 乘积
分析 :
定义 dp[i][j] = 前 i 个数字中间插入 j 个乘号时候的最大乘积是多少
初始化 dp[ i ][ 0 ] = NUM(1, i) 1 <= i <= len(NUM)
最后的结果则存于 dp[n][k]
状态转移方程为 dp[i][j] = max( dp[i][j] , dp[m][j-1] * NUM[m+1 ~ i] ) j-1 < m < i
注 : NUM[a~b] 表示 NUM 的第 a 位到第 b 位组成的数字
关于状态转移方程先来看一个例子 n = 4、k = 2、NUM = 1231
首先初始化
dp[1][0] = 1
dp[2][0] = 12
dp[3][0] = 123
dp[4][0] = 1231
然后安插 1 个乘号的时候各个长度的最大乘积
dp[2][1] = dp[1][0] * 2 = 2
dp[3][1] = max( dp[1][0]*23、dp[2][0]*3 ) = 36
dp[4][1] = max( dp[1][0]*231、dp[2][0]*31、dp[3][0]*1 ) = 372
接着是安插 2 个乘号的时候
dp[3][2] = dp[2][1] * 3 = 6
dp[4][2] = max( dp[2][1]*31、dp[3][1]*1 ) = 62
细细去推一下这个例子,可能就会发现更加理解了这个 dp
可以看出这个 dp 定义的第二维应该是阶段、而第一维是 dp 的状态
换句话说只有知道在各个长度安插 1 个乘号的结果才能推出各个长度安插 2 个乘号的结果
C++版
#include<bits/stdc++.h>
#define LL long long
using namespace std;
;
LL dp[maxn][maxn];
char num[maxn];
LL GetVal(int st, int en)
{
LL ret = ;
for(int i=st; i<=en; i++)
ret = ret * + (num[i] - ');
return ret;
}
int main(void)
{
int n, k;
while(~scanf("%d %d", &n, &k)){
scanf());
; i<=n; i++)
dp[i][] = GetVal(, i);
; j<=k-; j++)
; i<=n; i++)
for(int m=j; m<i; m++)
dp[i][j] = max(dp[i][j], dp[m][j-]*GetVal(m+, i));
printf(]);
}
;
}
JAVA大数版
import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
import java.math.*;
import java.util.Arrays;
public class Main {
static BigInteger[][] dp = new BigInteger[15][15];
public static void main(String[] args){
Scanner cin = new Scanner (new BufferedInputStream(System.in));
int n, k;
String s;
while(cin.hasNext()){
n = cin.nextInt();
k = cin.nextInt();
s = cin.next();
for(int i=1; i<=n; i++){
dp[i][0] = BigInteger.valueOf( Integer.parseInt(s.substring(0,i)) );
//System.out.println(dp[i][0]);
}
for(int j=1; j<=k-1; j++)
for(int i=j+1; i<=n; i++){
dp[i][j] = BigInteger.ZERO;
for(int m=j; m<i; m++){
if(dp[i][j].compareTo(dp[m][j-1].multiply( BigInteger.valueOf( Integer.parseInt(s.substring(m, i)) ) )) < 0)
dp[i][j] = dp[m][j-1].multiply( BigInteger.valueOf( Integer.parseInt(s.substring(m, i)) ) );
}
}
System.out.println(dp[n][k-1]);
}
}
}
最大 k 乘积问题 ( 经典区间DP )的更多相关文章
- POJ 1160 经典区间dp/四边形优化
链接http://poj.org/problem?id=1160 很好的一个题,涉及到了以前老师说过的一个题目,可惜没往那上面想. 题意,给出N个城镇的地址,他们在一条直线上,现在要选择P个城镇建立邮 ...
- poj 1390 Blocks (经典区间dp 方块消除)
Blocks Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4250 Accepted: 1704 Descriptio ...
- 蓝桥杯 乘积最大(区间dp、数据水的话long long,暴力就能过)
Description 今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋 ...
- ZOJ 3541 The Last Puzzle(经典区间dp)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3541 题意:有一排开关,有个开关有两个值t和d,t是按下开关后在t秒后会自 ...
- nyoj 737 石子合并 经典区间 dp
石子合并(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆 ...
- 51nod 1021 石子归并 - 区间dp(经典)
题目地址:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021 经典区间dp,dp[i][j] 表示将从 i 到 j 堆 ...
- 区间dp实战练习
题解报告:poj 2955 Brackets(括号匹配) Description We give the following inductive definition of a “regular br ...
- [NYIST15]括号匹配(二)(区间dp)
题目链接:http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=15 经典区间dp,首先枚举区间的大小和该区间的左边界,这时右边界也可计算出来.首先初 ...
- 题解报告:NYOJ #737 石子合并(一)(区间dp)
描述 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值 ...
随机推荐
- python中的装饰器练习
一:编写装饰器,为多个函数加上认证的功能(用户的账号密码) 要求登录成功一次,后续的函数都无需输入用户名和密码FLAG=False#此时还未登录 全局变量 写这个步骤的意义在于:方便 知道已经登录成功 ...
- Chapter03 第四节 c++的算术运算符
c++算术运算符 3.4.1 运算符的优先级和结合性 四则运算参考四则运算优先级,注意括号. 3.4.2 除法的默认类型转换和精度问题 /* * @Description: 除法 * @Author: ...
- java8 stream取出 最大值/最小值
注:转载请注明出处!!! 这里直接用取出多个对象中某个值 最大/最小 来进行举例 直接看代码 /** * 时间测试类 */ class TimeTest { private Date time; pu ...
- Hive-生成一个大文件(小文件合并)
set hive.execution.engine=mr; --在 map-reduce 作业结束时合并小文件.如启用,将创建 map-only 作业以合并目标表/分区中的文件. set hive.m ...
- 【Linux-驱动】驱动策略----自旋锁
自旋锁 自旋锁最多只能被一个内核任务持有.要是锁未被持有,请求它的内核任务便会立即得到它并继续执行.如果一个内核任务试图请求一个已经被别的内核任务持有的自旋锁,那么CPU就会一直尽心循环---旋转-- ...
- vue组件化编程应用
写几个小案例来理解vue的组件化编程思想,下面是一个demo. 效果图示: 功能: Add组件用于添加用户评论,提交后右边评论回复会立马显示数据.Item组件点击删除可以删除当前用户评论.当List组 ...
- 最长公共子序列(LCS) Easy
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. ...
- 大div中,三个小div水平居中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- http协议中常见的状态码以及请求方式,http协议的组成
请求状态码: 2xxx:表示请求成功,例如200. 3xxx:表示请求被重定向,表示完成请求,需要进一步操作,例如 302. 4xxx:表示请求错误,例如:404,资源没有找到. 5xxx:表示服务器 ...
- PC端网站微信扫码登录
需求分析:用户通过扫描我们网页的二维码,如果已经绑定我们平台的账户,即成功进入首页,否则提示先绑定个人微信账号. 1.绑定微信账号:是通过关注微信公众号实现绑定个人微信账号.首先通过后台接口获取到ti ...