费用提前计算的区间dp*3

本文通过三道例题深入解析费用流动态规划算法的应用技巧,包括如何预计算未来的费用变化,以及如何通过状态转移方程解决最优化问题。

嗯如题。
推荐学习论文

大概意思是
可以把未来的费用提前计算好。
素不素很神奇。

当前决策对未来的影响置于当前决策有关。所以可以天前算出来。

第一道:
bzoj 2037

要求的答案是 Σ(y-ti*vi)/1000
所以问题可以转化成
当前做出决策时会使其余的减少多少

当然一开始需要排序,问题转化为从起点往左或者往右

w[i][j]为Σsum-Σv[k] i<=k<=j 意为 除了ij之外的球的减少速度和
我们设

f[0][i][j]=max(f[0][i+1][j]-(egg[i+1].x-egg[i].x)*w[i+1][j],f[1][i+1][j]-(egg[j].x-egg[i].x)*w[i+1][j])+egg[i].y;

f[1][i][j]=max(f[1][i][j-1]-(egg[j].x-egg[j-1].x)*w[i][j-1],f[0][i][j-1]-(egg[j].x-egg[i].x)*w[i][j-1])+egg[j].y;

就没啥问题了

PS:WA了几次,因为没有赋负值。
然后一个i j挂了。呜呜呜

#include<cstdio>
#include<algorithm>
#include<cstring>
#define inf 0x3fffffff
using namespace std;
//by mars_ch
int n,x0;
struct data{
    int x,y,v;
}egg[1005];
int w[1005][1005];
int f[2][1005][1005];
int sum;
bool cmp(data a,data b)
{
    return a.x<b.x;
}
int main(){
    scanf("%d%d",&n,&x0);
    for(int i=1;i<=n;i++){
        scanf("%d",&egg[i].x);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&egg[i].y);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&egg[i].v);
        sum+=egg[i].v;
    }
    egg[++n].x=x0;
    sort(egg+1,egg+n+1,cmp);
    for(int i=1;i<=n;i++){
        for(int j=i;j<=n;j++){
            w[i][j]=sum;
            for(int k=i;k<=j;k++){
                w[i][j]-=egg[k].v;
            }
        }

    }
    memset(f,-0x3f,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        if(egg[i].x == x0)
        f[0][i][i]=f[1][i][i]=0;
    }
    for(int i=n;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            f[0][i][j]=max(f[0][i+1][j]-(egg[i+1].x-egg[i].x)*w[i+1][j],f[1][i+1][j]-(egg[j].x-egg[i].x)*w[i+1][j])+egg[i].y;

            f[1][i][j]=max(f[1][i][j-1]-(egg[j].x-egg[j-1].x)*w[i][j-1],f[0][i][j-1]-(egg[j].x-egg[i].x)*w[i][j-1])+egg[j].y;
        }
    }
    printf("%.3lf\n",(double)(1.0*max(f[0][1][n],f[1][1][n])/1000));
}

第二道:
很类似啦
poj 3042

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
//by mars_ch
int n,l;
int a[1005];
int f[2][1005][1005];
int main()
{
    scanf("%d%d",&n,&a[0]);
    int x=a[0];
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    sort(a,a+n+1);
    memset(f,0x3f,sizeof(f));
    for(int i=0;i<=n;i++)
    {
        if(a[i] == x)
        {
            f[1][i][i]=0;
            f[0][i][i]=0;
        }
    }
    for(int i=n;i>=0;i--)
    {
        for(int j=i+1;j<=n;j++)
        {
            f[0][i][j]=min(f[0][i+1][j]+(a[i+1]-a[i])*(n+1-j+i),f[1][i+1][j]+(a[j]-a[i])*(n+1-j+i));

            f[1][i][j]=min(f[1][i][j-1]+(a[j]-a[j-1])*(n+1-j+i),f[0][i][j-1]+(a[j]-a[i])*(n+1-j+i));
        }
    }
    printf("%d\n",min(f[0][0][n],f[1][0][n]));
}

第三道:
当时还不知道是费用流dp。看的题解
题号我记不得了。。我是罪人。。我去找。。

【永磁同步电机】基于模型预测控制MPC的永磁同步电机非线性终端滑模控制仿真研究(Simulink&Matlab代码实现)内容概要:本文围绕永磁同步电机(PMSM)的高性能控制展开,提出了一种结合模型预测控制(MPC)与非线性终端滑模控制(NTSMC)的先进控制策略,并通过Simulink与Matlab进行系统建模与仿真验证。该方法旨在克服传统控制中动态响应慢、鲁棒性不足等问题,利用MPC的多步预测和滚动优化能力,结合NTSMC的强鲁棒性和有限时间收敛特性,实现对电机转速和电流的高精度、快速响应控制。文中详细阐述了系统数学模型构建、控制器设计流程、参数整定方法及仿真结果分析,展示了该复合控制策略在抗干扰能力和动态性能方面的优越性。; 适合人群:具备自动控制理论、电机控制基础知识及一定Matlab/Simulink仿真能力的电气工程、自动化等相关专业的研究生、科研人员及从事电机驱动系统开发的工程师。; 使用场景及目标:①用于深入理解模型预测控制与滑模控制在电机系统中的融合应用;②为永磁同步电机高性能控制系统的仿真研究与实际设计提供可复现的技术方案与代码参考;③支撑科研论文复现、课题研究或工程项目前期验证。; 阅读建议:建议读者结合提供的Simulink模型与Matlab代码,逐步调试仿真环境,重点分析控制器设计逻辑与参数敏感性,同时可尝试在此基础上引入外部扰动或参数变化以进一步验证控制鲁棒性。
### 计算字符串距离的动态规划算法 #### 动态规划的核心概念 动态规划是一种解决多阶段决策过程最优化问题的方法。对于字符串距离问题,通常采用的是 **Levenshtein 距离** 或者称为编辑距离的概念[^2]。该算法的目标是最少的操作次数将一个字符串转换为另一个字符串。 #### 定义状态转移方程 设 `dp[i][j]` 表示将字符串 A 的前 i 个字符转化为字符串 B 的前 j 个字符所需的最小操作数,则可以定义以下状态转移关系: - 如果 `A[i-1] == B[j-1]`,则无需额外操作: \[ dp[i][j] = dp[i-1][j-1] \] - 否则,取以下三种情况中的最小值加一: - 插入操作:`dp[i][j] = dp[i][j-1] + 1` - 删除操作:`dp[i][j] = dp[i-1][j] + 1` - 替换操作:`dp[i][j] = dp[i-1][j-1] + 1` 最终的结果存储在 `dp[m][n]` 中,其中 m 和 n 分别是字符串 A 和 B 的长度[^4]。 #### 初始化条件 为了便于后续计算,需要初始化边界条件: - 当其中一个字符串为空时,另一字符串的距离为其长度(即全部插入或删除)。因此有: - \( dp[i][0] = i \),表示将 A 的前 i 个字符变为空字符串所需的操作数; - \( dp[0][j] = j \),表示将空字符串变为 B 的前 j 个字符所需的操作数。 #### Java 实现代码 以下是基于上述理论的 Java 实现代码: ```java public class EditDistance { public static int calStringDistance(String charA, String charB) { if (charA == null || charB == null) return -1; int m = charA.length(); int n = charB.length(); // 创建 DP 数组并初始化 int[][] dp = new int[m + 1][n + 1]; for (int i = 0; i <= m; i++) { dp[i][0] = i; } for (int j = 0; j <= n; j++) { dp[0][j] = j; } // 填充 DP 数组 for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (charA.charAt(i - 1) == charB.charAt(j - 1)) { dp[i][j] = dp[i - 1][j - 1]; } else { dp[i][j] = Math.min(dp[i - 1][j], // 删除 Math.min(dp[i][j - 1], // 插入 dp[i - 1][j - 1])) + 1; // 替换 } } } return dp[m][n]; // 返回结果 } public static void main(String[] args) { System.out.println(calStringDistance("abcdefg", "abcdef")); // 输出 1 } } ``` 此代码实现了 Levenshtein 距离的计算功能,并通过测试案例验证其正确性[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值