【总结】LCA小结

这些天一直在刷LCA的题目。。LCA的题目并不是很多,不过到现在为止还有几题没刷完,先做个小结。。

LCA一般用的主要有三种算法:

1、朴素算法,看两个结点的深度,深度大的沿父结点先往上走,知道两个结点的深度相同,然后同时向上走,直到他们两个点重合,这就是他们的LCA了。。这个算法简单,但是用的比较少。

2、LCA在线算法(ST算法),在线算法就是出现一个查询就查一个,LCA在线算法一般是向RMQ转化,首先先对整个树进行DFS,将遍历的结点按顺序几下,这样我们就生成了一个长度为(2*n-1)的欧拉序列(欧拉序列到底是什么意思我也不知道,只是知道他是按顺序遍历树生成的),与此同时,我们还顺便记录下了每个结点第一次出现在欧拉序列的位置pos,然后对这个欧拉序列进行RMQ(这里面存的是每一段深度最小的),查询时输入的是结点要注意把结点转化为欧拉序列中的位置。

3、LCA离线算法(tarjan),离线算法要先读入所有的查询,里面还要用到并查集,里面本质还不是很懂。。。

然后就是一些题目了

HDU2586 How far away ?

模板题。。。用在线和离线都写了一遍。。

ZOJ3195 Design the city

也是模板题。。。三个点的公式就是dist[a+dist[b+dist[c]-dist[lca(a,b)]-dist[lca(a,c)]-dist[lca(b,c)];

HDU2874 Connections between cities

大体还是模板,这里还需要判断一个不连通的状况,一个比较好的处理方法是给每个树染一个不相同的颜色(不连通是因为有多个树),然后这样处理下tarjan算法就不会出问题了。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=10010;
const int MAXE=20010;
const int MAXC=1000010;
int fa[MAXN];
struct EDGE
{
    int v,next;
    int dis;
}edge[MAXE];
struct QUEST
{
    int v,next;
    int num;
}q[MAXC<<1];
template <class T>
inline void scan_d(T &ret) {
    char c; ret=0;
    while((c=getchar())<'0'||c>'9');
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}
int head1[MAXN],head2[MAXN],size;
int dist[MAXN],lca[MAXC];
short anss[MAXC],anst[MAXC];
int vis[MAXN];
void init()
{
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    memset(dist,0,sizeof(dist));
    memset(vis,0,sizeof(vis));
    size=0;
}
void add_edge(int u,int v,int dis)
{
    edge[size].v=v;
    edge[size].dis=dis;
    edge[size].next=head1[u];
    head1[u]=size++;
}
void add_q(int u,int v,int i)
{
    q[size].v=v;
    q[size].num=i;
    q[size].next=head2[u];
    head2[u]=size++;
}
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void tarjan(int u,int mark)
{
    fa[u]=u;
    vis[u]=mark;
    for(int i=head2[u];i!=-1;i=q[i].next)
    {
        int v=q[i].v;
        if(vis[v]==mark)
        {
            lca[q[i].num]=find(v);
        }
    }
    for(int i=head1[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            dist[v]=dist[u]+edge[i].dis;
            tarjan(v,mark);
            fa[v]=u;
        }
    }
}
int main()
{
    int n,m,i,c;
    while(scanf("%d%d%d",&n,&m,&c)==3)
    {
        init();
        int u,v,x;
        while(m--)
        {
            scan_d(u);
            scan_d(v);
            scan_d(x);
            add_edge(u,v,x);
            add_edge(v,u,x);
        }
        size=0;
        for(i=0;i<c;i++)
        {
            scan_d(u);
            scan_d(v);
            add_q(u,v,i);
            add_q(v,u,i);
            anss[i]=u;
            anst[i]=v;
        }
        memset(lca,-1,sizeof(lca));
        int mark=0;
        for(i=1;i<=n;i++)
        {
            if(!vis[i])
                tarjan(i,++mark);
        }
        for(i=0;i<c;i++)
        {
            if(lca[i]==-1)
                printf("Not connected\n");
            else
                printf("%d\n",dist[anss[i]]+dist[anst[i]]-2*dist[lca[i]]);
        }
    }
    return 0;
}
HDU3078 Network
求两个点路径上第k大的点,求出两个点的lca,然后分别沿两个点向上走到LCA,并记录下走过了哪些点,然后排个序,然后输出就是。

/*************************************************************************
	> File Name: 3078.cpp
	> Author: tjw
	> Mail:
	> Created Time: 2014年10月08日 星期三 10时25分39秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
using namespace std;
const int MAXN=80010;
int dep[MAXN*2],set[MAXN*2],fa[MAXN],rank[MAXN*2],num;
int val[MAXN];
int dp[MAXN*2][30];
bool vis[MAXN];
struct EDGE
{
    int v,next;
}edge[MAXN*4];
int head[MAXN],size;
int Min(int a,int b)
{
    return dep[a]<dep[b]?a:b;
}
void init()
{
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    size=0;
}
void add_edge(int u,int v)
{
    edge[size].v=v;
    edge[size].next=head[u];
    head[u]=size++;
}
bool cmp(int x,int y)
{
    return x>y;
}
void dfs(int u,int deep,int fat)
{
    vis[u]=1;
    rank[u]=num;
    set[num]=u;
    dep[num++]=deep;
    fa[u]=fat;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(vis[v])
        	continue;
        dfs(v,deep+1,u);
        set[num]=u;
        dep[num++]=deep;
    }
}
void RMQ_init()
{
    int i,j;
    for(i=0;i<num;i++)
        dp[i][0]=i;
    for(j=1;(1<<j)<num;j++)
    {
        for(i=0;i+(1<<j)<num;i++)
        {
            dp[i][j]=Min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int RMQ(int l,int r)
{
    int k=(int)(log(r-l+1.0)/log(2.0));
    return Min(dp[l][k],dp[r-(1<<k)+1][k]);
}
int LCA(int l,int r)
{
    if(l>r)
        swap(l,r);
    return set[RMQ(l,r)];
}
int k;
int ans[MAXN*2];
void path(int s,int u)
{
    while(s!=u)
    {
        ans[k++]=val[u];
        u=fa[u];
    }
}
int main()
{
    int n,q,i;
    while(scanf("%d%d",&n,&q)==2)
    {
        for(i=1;i<=n;i++)
            scanf("%d",&val[i]);
        int u,v;
        init();
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        num=0;
        dfs(1,1,-1);
        int op,x,y;
        RMQ_init();
        while(q--)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==0)
            {
                val[x]=y;
                continue;
            }
            u=LCA(rank[x],rank[y]);
            k=0;
            ans[k++]=val[u];
            path(u,x);
            path(u,y);
            k--;
            if(op>k+1)
            {
                printf("invalid request!\n");
                continue;
            }
            sort(ans,ans+k+1,cmp);
            printf("%d\n",ans[op-1]);
        }
    }
    return 0;
}

POJ1986 Distance Queries

模板,他们说做这题之前还要看哪题才能理解题意,但是可以YY那个东西对这题来说是没什么用的(数据范围还是有用的,可以看1984)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=40010;
const int MAXE=20010;
struct EDGE
{
    int v,next;
    int dis;
}edge[MAXN<<1];
struct QEUT
{
    int v,next;
    int num;
}q[MAXE];
int head1[MAXN],head2[MAXN],size;
bool vis[MAXN];
int dist[MAXN],lca[MAXE],anss[MAXE],anst[MAXN],fa[MAXN];
void init()
{
    memset(vis,0,sizeof(vis));
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    memset(dist,0,sizeof(dist));
    size=0;
}
void add_edge(int u,int v,int dis)
{
    edge[size].v=v;
    edge[size].dis=dis;
    edge[size].next=head1[u];
    head1[u]=size++;
}
void add_q(int u,int v,int i)
{
    q[size].v=v;
    q[size].num=i;
    q[size].next=head2[u];
    head2[u]=size++;
}
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void tarjan(int u)
{
    fa[u]=u;
    vis[u]=1;
    for(int i=head2[u];i!=-1;i=q[i].next)
    {
        int v=q[i].v;
        if(vis[v])
        {
            lca[q[i].num]=find(v);
        }
    }
    for(int i=head1[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            dist[v]=dist[u]+edge[i].dis;
            tarjan(v);
            fa[v]=u;
        }
    }
}
int main()
{
    int n,m,i,k;
    while(scanf("%d%d",&n,&m)==2)
    {
        init();
        int u,v,c;
        char op;
        while(m--)
        {
            scanf("%d%d%d %c",&u,&v,&c,&op);
            add_edge(u,v,c);
            add_edge(v,u,c);
        }
        scanf("%d",&k);
        size=0;
        for(i=0;i<k;i++)
        {
            scanf("%d%d",&u,&v);
            add_q(u,v,i);
            add_q(v,u,i);
            anss[i]=u;
            anst[i]=v;
        }
        tarjan(1);
        for(i=0;i<k;i++)
        {
            printf("%d\n",dist[anss[i]]+dist[anst[i]]-2*dist[lca[i]]);
        }
    }
}
POJ2763 Housewife Wind
树状数组+LCA,把那一串欧拉序列看成树状数组维护的对象,每次改变走过一段路需要的时间的时候,将这次的时间和原来的时间做差,然后从1-pos[]+1(pos是两个点中大的那个点)加上改变的值,前面dfs顺便记录下这个点结束遍历的位置,然后1-那个位置减去改变的值就可以了。

/*************************************************************************
	> File Name: poj2763.cpp
	> Author: tjw
	> Mail: 
	> Created Time: 2014年10月08日 星期三 17时31分31秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
using namespace std;
const int MAXN=100010;
int c[MAXN];
int set[MAXN<<1],dep[MAXN<<1],dist[MAXN],rank[MAXN],fa[MAXN];
struct EDGE
{
    int v,next;
    int dis;
}edge[MAXN<<1];
int head[MAXN],size;
bool vis[MAXN];
void init()
{
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    memset(c,0,sizeof(c));
    size=0;
}
void add_edge(int u,int v,int dis)
{
    edge[size].v=v;
    edge[size].dis=dis;
    edge[size].next=head[u];
    head[u]=size++;
}
int Min(int a,int b)
{
    return dep[a]<dep[b]?a:b;
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int val)
{
    while(x<MAXN)
    {
        c[x]+=val;
        x+=lowbit(x);
    }
}
int sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}
int num;
int ed[MAXN];
void dfs(int u,int deep)
{
    vis[u]=1;
    rank[u]=num;
    set[num]=u;
    dep[num++]=deep;
    for(int i=head[u];i!=-1;i=edge[i].v)
    {
        int v=edge[i].v;
        if(vis[v])
            return;
        fa[v]=u;
        dist[v]=dist[u]+edge[i].v;
        dfs(v,deep+1);
        set[num]=u;
        dep[num++]=deep;
    }
    ed[u]=num;
}
int dp[MAXN<<1][20];
void RMQ_init()
{
    int i,j;
    for(i=0;i<num;i++)
        dp[i][0]=i;
    for(j=1;(1<<j)<num;j++)
    {
        for(i=0;i+(1<<j)<num;i++)
        {
            dp[i][j]=Min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int RMQ(int l,int r)
{
    int k=(int)(log(r-l+1.0)/log(2.0));
    return Min(dp[l][k],dp[r-(1<<k)+1][k]);
}
int LCA(int l,int r)
{
    if(l>r)
        swap(l,r);
    return set[RMQ(l,r)];
}
int u[MAXN],v[MAXN],val[MAXN];
int main()
{
    int n,q,s,i;
    while(scanf("%d%d%d",&n,&q,&s)==3)
    {
        init();
        for(i=1;i<n;i++)
        {
            scanf("%d%d%d",&u[i],&v[i],&val[i]);
            add_edge(u[i],v[i],val[i]);
            add_edge(v[i],u[i],val[i]);
        }
        dist[1]=0;
        fa[1]=-1;
        dfs(1,1);
        RMQ_init();
        while(q--)
        {
            int op,x,y;
            scanf("%d",&op);
            if(op==0)
            {
                scanf("%d",&x);
                int xx=rank[s],yy=rank[x];
                int cc=LCA(xx,yy);
                int z=rank[cc];
                printf("%d\n",sum(xx+1)+sum(yy+1)-2*sum(cc+1)+dist[s]+dist[x]-2*dist[cc]);
                s=x;
            }
            else
            {kai shi
                scanf("%d%d",&x,&y);
                int xx=u[x];
                int yy=v[x];
                int temp=y-val[x];
                val[x]=y;
                if(fa[xx]==yy)
                    swap(xx,yy);
                add(rank[yy]+1,temp);
                add(ed[yy]+1,-temp);
            }
        }
    }
    return 0;
}
POJ3694 Network
LCA朴素算法,先双连通缩点求桥,然后朴素算法沿这两个点向上跑,遇到桥就数量减1,然后把这个桥去掉。。

/*************************************************************************
	> File Name: poj3964.cpp
	> Author: tjw
	> Mail: 
	> Created Time: 2014年10月08日 星期三 20时17分08秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
using namespace std;
const int MAXN=100010;
const int MAXE=200010;
struct EDGE
{
    int v,next,uesd;
}edge[MAXE<<1];
int pre[MAXN],low[MAXN],bcc_cnt,fa[MAXN],dfs_clock;
int head[MAXN],size;
int vis[MAXN],bridge[MAXN];
void init()
{
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    memset(bridge,0,sizeof(bridge));
    dfs_clock=bcc_cnt=size=0;
}
void add_edge(int u,int v)
{
    edge[size].v=v;
    edge[size].uesd=0;
    edge[size].next=head[u];
    head[u]=size++;
}
void tarjan(int u)
{
    pre[u]=low[u]=++dfs_clock;
    vis[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        if(!edge[i].uesd)
        {
            edge[i].uesd=edge[i^1].uesd=1;
            int v=edge[i].v;
            if(!vis[v])
            {
                fa[v]=u;
                tarjan(v);
                low[u]=min(low[u],low[v]);
                if(pre[u]<low[v])
                {
                    bcc_cnt++;
                    bridge[v]=1;
                }
            }
            else if(vis[v]==1)
                low[u]=min(low[u],pre[v]);
        }
    }
    vis[u]=2;
}
void LCA(int u,int v)
{
    if(pre[u]>pre[v])
        swap(pre[u],pre[v]);
    while(pre[v]>pre[u])
    {
        if(bridge[v])
        {
            bcc_cnt--;
            bridge[v]=0;
        }
        v=fa[v];
    }
    while(u!=v)
    {
        if(bridge[u])
        {
            bcc_cnt--;
            bridge[u]=0;
        }
        if(bridge[v])
        {
            bcc_cnt--;
            bridge[v]=0;
        }
        u=fa[u];
        v=fa[v];
    }
}
int main()
{
    int n,m,q,flag=1;
    while(scanf("%d%d",&n,&m)==2)
    {
        if(n==0&&m==0)
            break;
        int u,v;
        init();
        while(m--)
        {
            scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        tarjan(1);
        scanf("%d",&q);
        printf("Case %d:\n",flag++);
        while(q--)
        {
            scanf("%d%d",&u,&v);
            LCA(u,v);
            printf("%d\n",bcc_cnt);
        }
        printf("\n");
    }
    return 0;
}
POJ3417 Network

LCA+简单树形DP,对于每加一条边,就将这两个点和他们的lca组成的环上的边都加1,,然后判断每一条边,如果没有加1(就是0),可以把这条边删去加上任意一条新加的边,所以+=q,等于1的话,就一定要删去新加的边和当前边,所以+=1,大于1,无论怎么删都不可能,所以对两个点dp[u]+=1,dp[v]+=1,dp[lca]-=2,然后对整个树dfs从底部更新上来就可以了。

/*************************************************************************
	> File Name: poj3417.cpp
	> Author: tjw
	> Mail: 
	> Created Time: 2014年10月10日 星期五 09时03分09秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
using namespace std;
const int MAXN=100010;
struct EDGE
{
    int v,next;
}edge[MAXN<<1];
int head1[MAXN],head2[MAXN],size;
bool vis[MAXN];
int fa[MAXN],lca[MAXN];
struct QUEST
{
    int v,next;
    int num;
}q[MAXN<<1];
void init()
{
    memset(vis,0,sizeof(vis));
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    size=0;
}
void add_edge(int u,int v)
{
    edge[size].v=v;
    edge[size].next=head1[u];
    head1[u]=size++;
}
void add_q(int u,int v,int i)
{
    q[size].v=v;
    q[size].num=i;
    q[size].next=head2[u];
    head2[u]=size++;
}
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void tarjan(int u)
{
    if(vis[u])
        return;
    vis[u]=1;
    fa[u]=u;
    for(int i=head2[u];i!=-1;i=q[i].next)
    {
        int v=q[i].v;
        if(vis[v])
        {
            lca[q[i].num]=find(v);
        }
    }
    for(int i=head1[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            tarjan(v);
            fa[v]=u;
        }
    }
}
int dp[MAXN];
void dfs(int u)
{
    if(vis[u])
        return;
    vis[u]=1;
    for(int i=head1[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(vis[v])
            continue;
        dfs(v);
        dp[u]+=dp[v];
    }
}
int x[MAXN],y[MAXN];
int main()
{
    int n,m,i;
    while(scanf("%d%d",&n,&m)==2)
    {
        init();
        int u,v;
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        size=0;
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            add_q(u,v,i);
            add_q(v,u,i);
            x[i]=u;
            y[i]=v;
        }
        memset(dp,0,sizeof(dp));
        tarjan(1);
        for(i=1;i<=m;i++)
        {
            u=x[i],v=y[i];
            dp[u]++;
            dp[v]++;
            dp[lca[i]]-=2;
        }
        int ans=0;
        memset(vis,0,sizeof(vis));
        dfs(1);
        for(i=2;i<=n;i++)
        {
            if(dp[i]==0)
                ans+=m;
            else if(dp[i]==1)
                ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}


POJ3728 The merchant
这题总体感觉很复杂,,,先上码

/*************************************************************************
	> File Name: poj3728.cpp
	> Author: tjw
	> Mail: 
	> Created Time: 2014年10月10日 星期五 14时48分39秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define ll long long
using namespace std;
const int MAXN=50010;
int up[MAXN],down[MAXN],Max[MAXN],Min[MAXN];
int lca,val[MAXN];
int head1[MAXN],head2[MAXN],head3[MAXN],size,sz;
bool vis[MAXN];
int ans[MAXN];
struct EDGE
{
    int v,next;
}edge[MAXN<<1];
struct QUEST
{
    int u,v,next;
}q[MAXN<<1];
struct ANS 
{
    int v,next;
    int num;
}e[MAXN<<1];
void init()
{
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    memset(head3,-1,sizeof(head3));
    memset(vis,0,sizeof(vis));
    size=sz=0;
}
void add_edge(int u,int v)
{
    edge[size].v=v;
    edge[size].next=head1[u];
    head1[u]=size++;
}
void add_q(int u,int v)
{
    q[size].u=u;
    q[size].v=v;
    q[size].next=head2[u];
    head2[u]=size++;
}
void add_ans(int u,int k)
{
    e[sz].next=head3[u];
    e[sz].num=k;
    head3[u]=sz++;
}
int fa[MAXN];
int update(int u)
{
    if(fa[u]==u)
        return u;
    int par=fa[u];
    fa[u]=update(fa[u]);
    up[u]=max(up[u],max(up[par],Max[par]-Min[u]));
    down[u]=max(down[u],max(down[par],Max[u]-Min[par]));
    Max[u]=max(Max[u],Max[par]);
    Min[u]=min(Min[u],Min[par]);
    return fa[u];
}
void tarjan(int u)
{
    if(vis[u])
        return;
    vis[u]=1;
    fa[u]=u;
    for(int i=head2[u];i!=-1;i=q[i].next)
    {
        int v=q[i].v;
        if(vis[v])
        {
            lca=update(v);
            add_ans(lca,i);
        }
    }
    for(int i=head1[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(!vis[v])
        {
            tarjan(v);
            fa[v]=u;
        }
    }
    for(int i=head3[u];i!=-1;i=e[i].next)
    {
        int k=e[i].num;
        int x=q[k].u,y=q[k].v;
        if(k&1)
        {
            swap(x,y);
            k=k^1;
        }
        k/=2;
        update(x);
        update(y);
        ans[k]=max(up[x],down[y]);
        ans[k]=max(ans[k],Max[y]-Min[x]);
    }
}
int main()
{
    int n,q,i;
    while(scanf("%d",&n)==1)
    {
        init();
        for(i=1;i<=n;i++)
        {
            scanf("%d",&val[i]);
            up[i]=down[i]=0;
            Max[i]=Min[i]=val[i];
        }
        int u,v;
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        scanf("%d",&q);
        size=0;
        for(i=0;i<q;i++)
        {
            scanf("%d%d",&u,&v);
            add_q(u,v);
            add_q(v,u);
        }
        tarjan(1);
        for(i=0;i<q;i++)
        {
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}

基于STM32 F4的永磁同步电机无位置传感器控制策略研究内容概要:本文围绕基于STM32 F4的永磁同步电机(PMSM)无位置传感器控制策略展开研究,重点探讨在不依赖物理位置传感器的情况下,如何通过法实现对电机转子位置和速度的精确估计与控制。文中结合嵌入式开发平台STM32 F4,采用如滑模观测器、扩展卡尔曼滤波或高频注入法等先进观测技术,实现对电机反电动势或磁链的估,进而完成无传感器矢量控制(FOC)。同时,研究涵盖系统建模、控制法设计、仿真验证(可能使用Simulink)以及在STM32硬件平台上的代码实现与调试,旨在提高电机控制系统的可靠性、降低成本并增强环境适应性。; 适合人群:具备一定电力电子、自动控制理论基础和嵌入式开发经验的电气工程、自动化及相关专业的研究生、科研人员及从事电机驱动开发的工程师。; 使用场景及目标:①掌握永磁同步电机无位置传感器控制的核心原理与实现方法;②学习如何在STM32平台上进行电机控制法的移植与优化;③为开发高性能、低成本的电机驱动系统提供技术参考与实践指导。; 阅读建议:建议读者结合文中提到的控制理论、仿真模型与实际代码实现进行系统学习,有条件者应在实验平台上进行验证,重点关注观测器设计、参数整定及系统稳定性分析等关键环节。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值