《紫书:动态规划初步》总结二

本文探讨了多阶图的最短路径问题,介绍了一种通过动态规划求解的方法,包括状态定义、转移方程及核心代码实现。此外,还讨论了0-1背包问题的不同类型及其解决方案,以及在特定场景下的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多阶图的最短路

对于一个数字矩阵,从左往右走,每次可以直右,右上,右下。走到最后的数字和最小为多少。

同时输出字典序最小的走过的行号。

这里有n^2的状态,但可以容易发现,每一列的n个状态可以划分为一个阶段,实质上是阶段之间的转移

枚举每个阶段,对于每个阶段的每个状态分别转移即可。

dp[i]][j]表示从i、j开始走到最后的最小和,这是满足最优子结构的。

维护每个状态下一次最优路径的最小行号。(遍历排序即可)。这种链表式的答案,可以保证局部字典序最小,实现全局最小。

[可能你这边比较小,但是答案前面的更小,我从前面的开始是不会经过后面较小的(如果后面较小的前面较大)]。

核心代码:

        for(int j=c;j>=1;j--)
            for(int i=1;i<=r;i++){
                if(j==c)dp[i][j]=A[i][j];
                else{
                    int rows[3]={i,i-1,i+1};
                    if(i==1)rows[1]=r;
                    if(i==r)rows[2]=1;
                    sort(rows,rows+3);
                    for(int k=0;k<3;k++){
                        int v=dp[rows[k]][j+1]+A[i][j];
                        if(v<dp[i][j]){
                            dp[i][j]=v;ans[i][j]=rows[k];
                        }
                    }
                }
                if(j==1&&dp[i][1]<res){first=i;res=dp[i][1];}
            }
        printf("%d",first);
        for(int i=ans[first][1],j=2;j<=c;i=ans[i][j],j++){
            printf(" %d",i);
        }
        printf("\n%d\n",res);

0-1 背包问题

1、物品无限的背包问题

类似于硬币问题:C->C-V[I]的状态,dp[C]=max(dp[C-V[i]]+W[i]);

2、0-1背包问题

每个物品只能取一次。

所以不能重复遍历了,因为你也不知道哪些已经被选了(状压?数字大的时候没办法状压)

考虑阶段的问题,在把前i个物品放进背包里属于第i个阶段,每个阶段切换到下一个阶段只用判断要不要放新的物品即可。

每个阶段有背包为C以内的状态。dp[i][C]=max(dp[i-1][C-V[i]])。如果我要选择第i个物品,那么对于之前的背包状态必然只有C-V[i].

对内存继续优化,可以考虑滚动数组,因为:状态转移方程算C只会用到C-v[i].那么也就是说,算dp[i][C]的时候,dp[i][C]并没有更新,那么把i去掉,每次计算后面的没更新,还是i-1的阶段

Jin Ge Jin Qu hao:UVA - 12563 

题意:在时间t-1内选择足够多的歌曲,如果有多个选择,选择总歌曲时长最大的。

就是在t-1大的背包里放尽可能多个的歌曲,维护两个背包,一个记录歌曲数量,另一个记录歌曲总时长。

但是背包取优先级是先数量,数量相同的情况再去取总时长更大的。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

#define ll long long
#define M 404
#define inf 0x3f3f3f3f

int T,n,V;
int dp[181*55],pd[181*55];

int main(){
    cin>>T;
    int cnt=0;
    while(T--){
        scanf("%d%d",&n,&V);
        memset(dp,0,sizeof(dp));
        memset(pd,0,sizeof(pd));
        for(int i=1;i<=n;i++){
            int w;scanf("%d",&w);
            for(int j=V-1;j>=0;j--)if(j>=w){
                if((dp[j-w]+1>dp[j])||(dp[j-w]+1==dp[j]&&pd[j-w]+w>pd[j])){
                    dp[j]=dp[j-w]+1;
                    pd[j]=pd[j-w]+w;
                }
            }
        }
        printf("Case %d: %d %d\n",++cnt,dp[V-1]+1,pd[V-1]+678);
    }
}

这里突然想到前天训练赛没做出来的一道01背包题目:

题意:有n块砖,已知长和宽,选择一些把宽朝上作为第一层,在第二次把剩下让长朝上。

保证总长度小于第一层,求解让第一层尽可能的短,最短长度。必须用完所有砖。

假如取了1、2作为第一层,3、4、5作为第二层。

a1+a2>=b3+b4+b5;

∑ai-a3-a4-a5>=b3+b4+b5;

∑ai>=a3+b3 + a4+b4 + a5+b5;

必须满足这样的关系,并且使得3、4、5的a3、a4、a5尽可能大,这样的话∑a-a3-a4-a5会尽可能的小。

相等于有n个物品,体积为ai+bi,价值为ai,背包大小为ai的和,往里面 放尽可能多的。

内容概要:本文详细介绍了如何利用Simulink进行自动代码生成,在STM32平台上实现带57次谐波抑制功能的霍尔场定向控制(FOC)。首先,文章讲解了所需的软件环境准备,包括MATLAB/Simulink及其硬件支持包的安装。接着,阐述了构建永磁同步电机(PMSM)霍尔FOC控制模型的具体步骤,涵盖电机模型、坐标变换模块(如Clark和Park变换)、PI调节器、SVPWM模块以及用于抑制特定谐波的陷波器的设计。随后,描述了硬件目标配置、代码生成过程中的注意事项,以及生成后的C代码结构。此外,还讨论了霍尔传感器的位置估算、谐波补偿器的实现细节、ADC配置技巧、PWM死区时间和换相逻辑的优化。最后,分享了一些实用的工程集成经验,并推荐了几篇有助于深入了解相关技术和优化控制效果的研究论文。 适合人群:从事电机控制系统开发的技术人员,尤其是那些希望掌握基于Simulink的自动代码生成技术,以提高开发效率和控制精度的专业人士。 使用场景及目标:适用于需要精确控制永磁同步电机的应用场合,特别是在面对高次谐波干扰导致的电流波形失真问题时。通过采用文中提供的解决方案,可以显著改善系统的稳定性和性能,降低噪声水平,提升用户体验。 其他说明:文中不仅提供了详细的理论解释和技术指导,还包括了许多实践经验教训,如霍尔传感器处理、谐波抑制策略的选择、代码生成配置等方面的实际案例。这对于初学者来说是非常宝贵的参考资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值