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

本文介绍了一种使用动态规划解决数字分割以获得最大乘积的问题。通过添加虚拟前导'1*'简化了问题,并详细解释了状态表示、转移方程及边界条件。最后给出了完整的代码实现。

题目链接: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 }

 

基于数据驱动的 Koopman 算子的递归神经网络模线性化,用于纳米定位系统的预测控制研究(Matlab代码实现)内容概要:本文围绕“基于数据驱动的Koopman算子的递归神经网络模线性化”展开,旨在研究纳米定位系统的预测控制方法。通过结合数据驱动技术与Koopman算子理论,将非线性系统动态近似为高维线性系统,进而利用递归神经网络(RNN)建模并实现系统行为的精确预测。文中详细阐述了模构建流程、线性化策略及在预测控制中的集成应用,并提供了完整的Matlab代码实现,便于科研人员复现实验、优化算法并拓展至其他精密控制系统。该方法有效提升了纳米级定位系统的控制精度与动态响应性能。; 适合人群:具备自动控制、机器学习或信号处理背景,熟悉Matlab编程,从事精密仪器控制、智能制造或先进控制算法研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①实现非线性动态系统的数据驱动线性化建模;②提升纳米定位平台的轨迹跟踪与预测控制性能;③为高精度控制系统提供可复现的Koopman-RNN融合解决方案; 阅读建议:建议结合Matlab代码逐段理解算法实现细节,重点关注Koopman观测矩阵构造、RNN训练流程与模预测控制器(MPC)的集成方式,鼓励在实际硬件平台上验证并调整参数以适应具体应用场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值