存在免费套餐的最小生成树 Uva1151

本文探讨了在有限套餐选择下求最小生成树的问题,通过枚举套餐并结合Kruskal算法,提出了一种有效降低复杂度的方法。文章详细介绍了三种思路的优缺点,并最终确定了一种高效算法。

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

题意:
求最小生成树。( n 2 n^2 n2条边:需要自己算一共有 n n n个点的坐标)
不过你可以选择一个套餐,花费 c c c使得套餐内点全部连通。
套餐数量 q ≤ 8 , n ≤ 1000 q≤8,n≤1000 q8n1000
题解:
套餐数量较少,我们可以枚举(二进制即可)。
枚举之后把所有包含的边权赋值为 0 0 0
求最小生成树并且能够使得(边权赋值为 0 0 0的), p r i m prim prim不太好实现。
思路一:
枚举 ∗ ( *( (排序新边+ k r u s k a l ) kruskal) kruskal)
显然复杂度为 2 8 ∗ ( 8 ∗ n + 2 n 2 l o g 2 n + n 2 ) ≈ 1 0 8 2^8*(8*n+2n^2log_2n+n^2)≈10^8 28(8n+2n2log2n+n2)108朝上
思路二:
我们考虑免费套餐之后,其实我们只需要判连通即可,对枚举选中的免费套餐里的点连通,
再跑最小生成树,当所有点连通就退出。
但是这样的复杂度也是 2 8 ∗ ( 8 ∗ n + n 2 + n l o g n ) + 2 n 2 l o g n 2^8*(8*n+n^2+nlogn)+2n^2logn 28(8n+n2+nlogn)+2n2logn,常数小了很多但是还是不行。
主要在于每次求最小生成树用了 n 2 n^2 n2条边(最多,但是如果有一个点特别远,就会卡到 n 2 n^2 n2)
思路三:
我们考虑先做出一个最小生成树,对于上面的边能够使得所有点连通,我们每次对套餐内的点连通后,至多处理 n − 1 n-1 n1条边(如果这条边无法影响就不加上价值)。再往后遍历也是没有意义的。(因为如果较大的边连接的点在套餐里,那么已经被选择过了,如果不在:那为什么不选前面的边呢。
复杂度: 2 8 ( 8 ∗ n + n − 1 ) = 1 e 6 2^8(8*n+n-1)=1e^6 28(8n+n1)=1e6,因为 2 ∗ 9 = 18 2*9=18 29=18

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<cctype>
#include<string>
#include<cmath>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

#define ll long long
#define inf 0x3f3f3f3f
#define eps 1e-6

const int maxn = 10010;

int n,q,cnt=0;
int f[1010];ll value[10];
ll d[1010][1010];
pair<ll,ll>pos[1010];
vector<int>G[10],tree;

int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
void uni(int x,int y){f[find(x)]=find(y);}
bool query(int x,int y){return find(x)==find(y);}

struct node{
    int x,y;ll dist;
    friend bool operator < (node a,node b){
        return a.dist<b.dist;
    }
}A[1000010];

void init(){
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            d[j][i]=d[i][j]=(pos[i].first-pos[j].first)*(pos[i].first-pos[j].first)+(pos[i].second-pos[j].second)*(pos[i].second-pos[j].second);
        }
    }
    cnt=0;
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            A[++cnt]=node{i,j,d[i][j]};
        }
    }
    sort(A+1,A+1+cnt);
    tree.clear();
    for(int i=1;i<=n;i++)f[i]=i;
    int now=n;
    for(int i=1;i<=cnt;i++){
        if(!query(A[i].x,A[i].y)){
            tree.push_back(i);
            uni(A[i].x,A[i].y);
            now--;
            if(now==1)break;
        }
    }
}

int main(){
    int T;scanf("%d",&T);
    for(int kase=1;kase<=T;kase++){
        scanf("%d%d",&n,&q);
        FOR(i,1,q){
            int num;scanf("%d%lld",&num,&value[i]);
            G[i].clear();
            FOR(j,1,num){
                int x;scanf("%d",&x);
                G[i].push_back(x);
            }
        }
        FOR(i,1,n){
            scanf("%lld%lld",&pos[i].first,&pos[i].second);
        }
        init();
        ll ans=0x3f3f3f3f3f3f3f3f;
        for(int i=0;i<(1<<q);i++){
            for(int j=1;j<=n;j++)f[j]=j;
            ll res=0;
            for(int j=1;j<=q;j++){
                int x=(1<<(j-1));
                if(i&x){
                    res+=value[j];
                    for(int k=0;k<G[j].size()-1;k++){
                        uni(G[j][k],G[j][k+1]);
                    }
                }
            }
            for(int j=0;j<tree.size();j++){
                int u=tree[j];
                if(!query(A[u].x,A[u].y)){
                    uni(A[u].x,A[u].y);
                    res+=A[u].dist;
                }
            }
            ans=min(res,ans);
        }
        cout<<ans<<endl;if(kase<T)puts("");
    }
}

内容概要:本文详细介绍了如何利用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、付费专栏及课程。

余额充值