RQNOJ 311 [NOIP2000]乘积最大:划分型dp

题目链接:https://www.rqnoj.cn/problem/311

题意:

  给你一个长度为n的数字,用t个乘号分开,问你分开后乘积最大为多少。(6<=n<=40,1<=k<=30)

题解:

  简化问题:

    给原数字之前添加一个"1 *",乘号不计入数量,对答案无影响。

    例如:"1231"可以变成"(1*)1231"。

  表示状态:

    dp[i][j] = max num(最后一个乘号之前的最大乘积)

    i:此时在第i个数的前面添了一个乘号

    j:用了j个乘号

    例1:"(1*)12*31":

      dp[2][1] = 12 (数位从0开始从左向右编号)

    例2:"(1*)12*3*1"

      dp[3][2] = 12*3 = 36

  找出答案:

    max dp[i][t] * cal_sec(i,n-1)

    cal_sec(x,y)将数字串中[x,y]这个区间的字符串转化为数字

    例如:设n=4,t=1.

       此时为"(1*)12*31"

       则此时这种方案的乘积为dp[2][1]* "31" = 12*31

  如何转移:

    dp[i][j] = max dp[k][j-1] * cal_sec(k,i-1)

    在前面的某一段乘积后面再续上一串数字,达到第i位,用了j个乘号。

    前面的某一段乘积:枚举最后一个乘号在第k个数字之前,用了j-1个乘号。

    要续的数字:从第k位到i-1位 = cal_sec(k,i-1)

  边界条件:

    初始时用了0个乘号,但乘积为1。

    例如:"(1*)1231".

    特判:如果输入的数字就是0,则直接返回0.

  注:输入用string,答案用long long存。

    数据水。。。否则高精。。。

AC Code:

 1 // state expression:
 2 // dp[i][j] = max num
 3 // i: last ‘*‘ is in front of ith bit
 4 // j: used j ‘*‘
 5 //
 6 // find the answer:
 7 // max dp[i][t] * cal_sec(i,len-1)
 8 //
 9 // transferring:
10 // dp[i][j] = max dp[k][j-1] * cal_sec(k,i-1)
11 //
12 // boundary:
13 // if input == 0: return 0
14 // else dp[0] = 1, others = -1
15 #include <iostream>
16 #include <stdio.h>
17 #include <string.h>
18 #define MAX_N 45
19 #define MAX_K 35
20
21 using namespace std;
22
23 int n,t;
24 long long ans;
25 long long dp[MAX_N][MAX_K];
26 long long sec[MAX_N][MAX_N];
27 string s;
28
29 void read()
30 {
31     cin>>n>>t>>s;
32 }
33
34 long long cal_sec(int x,int y)
35 {
36     if(sec[x][y]!=-1) return sec[x][y];
37     long long res=0;
38     for(int i=x;i<=y;i++)
39     {
40         res=res*10+s[i]-‘0‘;
41     }
42     return sec[x][y]=res;
43 }
44
45 void solve()
46 {
47     memset(sec,-1,sizeof(sec));
48     memset(dp,-1,sizeof(dp));
49     dp[0][0]=1;
50     for(int i=1;i<n;i++)
51     {
52         for(int j=1;j<=t && j<=i;j++)
53         {
54             for(int k=0;k<i;k++)
55             {
56                 if(dp[k][j-1]!=-1)
57                 {
58                     dp[i][j]=max(dp[i][j],dp[k][j-1]*cal_sec(k,i-1));
59                 }
60             }
61         }
62     }
63     ans=0;
64     for(int i=0;i<n;i++)
65     {
66         if(dp[i][t]!=-1) ans=max(ans,dp[i][t]*cal_sec(i,n-1));
67     }
68 }
69
70 void print()
71 {
72     cout<<ans<<endl;
73 }
74
75 int main()
76 {
77     read();
78     solve();
79     print();
80 }
时间: 2024-10-14 14:05:40

RQNOJ 311 [NOIP2000]乘积最大:划分型dp的相关文章

乘积最大---区间型dp

题目描述 Description 今年是国际数学联盟确定的"2000--世界数学年",又恰逢我国著名数学家华罗庚先生诞辰90周年.在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加.活动中,主持人给所有参加活动的选手出了这样一道题目: 设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大. 同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子: 有一个数字串:31

codevs3162抄书问题(划分型dp)

3162 抄书问题 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 现在要把M本有顺序的书分给K个人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一.第三.第四本数给同一个人抄写.现在请你设计一种方案,使得复制时间最短.复制时间为抄写页数最多的人用去的时间. 输入描述 Input Description 第一行两个整数M.K:(K<=M<=100

Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)

描述 http://codevs.cn/problem/1040/ 与Codevs_1017_乘积最大很像,都是划分型dp. 给出一个字符串和几个单词,要求将字符串划分成k段,在每一段中求共有多少单词(两个单词不能共享第一个字母),将每一段中的单词个数相加,求最大值. 1040 统计单词个数 2001年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 给出一个长度不超过200的由小写英文字母组成的字母串(约

HDU1561 The more, The Better(树型DP)

题目是有n个存有宝藏的城堡,攻克任何一个城堡都需要先攻克0个或其他1个城堡,问攻克m个城堡最多能得到多少宝藏. 题目给的城堡形成一个森林,添加一个超级根把森林连在一起就是树了,那么就考虑用树型DP: dp[u][m]表示以u结点为根的子树攻克m个结点的最大价值 但是这样转移太难了,根是从每个孩子通过各自分配若干的城堡去攻克转移的,一个排列组合数,阶乘,是指数级的时间复杂度! 看了题解,原来这是依赖背包,没看背包九讲..不过网上的博客似乎没说清楚,事实上这个状态应该是三个维度来表示: dp[u][

POJ3659 Cell Phone Network(树上最小支配集:树型DP)

题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. 树上的每个结点作为其子树的根可以有三个状态: 不属于支配集且还没被支配 不属于支配集但被其孩子支配 属于支配集 那么就是用dp[u][1\2\3]来表示动归的状态. 123转移该怎么转移就怎么转移..最后的结果就是min(dp[root][2],dp[root][3]). 要注意的是对于有些结点前2

HDU_1561_The more, The Better_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7031    Accepted Submission(s): 4121 Problem Description ACboy很喜欢玩一种战略游戏,

HDU_1520_Anniversary party_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8233    Accepted Submission(s): 3574 Problem Description There is going to b

二叉苹果树(树型DP+背包)

二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树: 2   5 \  / 3  4 \  / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 程序名:apple 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=

POJ_1088 滑雪(记忆型DP+DFS)

Description Michael喜欢滑雪,这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小.在上面的例子