【刷题】位运算

2 n 2^n 2n

1<<n

判断某一位是否为1

s&1<<k

将上面两个组合,可以得到判断一个集合中哪些内容包含,遍历所有情况。

100140. 关闭分部的可行集合数目

一个公司在全国有 n 个分部,它们之间有的有道路连接。一开始,所有分部通过这些道路两两之间互相可以到达。

公司意识到在分部之间旅行花费了太多时间,所以它们决定关闭一些分部(也可能不关闭任何分部),同时保证剩下的分部之间两两互相可以到达且最远距离不超过 maxDistance 。

两个分部之间的 距离 是通过道路长度之和的 最小值 。

给你整数 n ,maxDistance 和下标从 0 开始的二维整数数组 roads ,其中 roads[i] = [ui, vi, wi] 表示一条从 ui 到 vi 长度为 wi的 无向 道路。

请你返回关闭分部的可行方案数目,满足每个方案里剩余分部之间的最远距离不超过 maxDistance。

注意,关闭一个分部后,与之相连的所有道路不可通行。

注意,两个分部之间可能会有多条道路。
示例 1:
在这里插入图片描述
输入:n = 3, maxDistance = 5, roads = [[0,1,2],[1,2,10],[0,2,10]]
输出:5
解释:可行的关闭分部方案有:

  • 关闭分部集合 [2] ,剩余分部为 [0,1] ,它们之间的距离为 2 。
  • 关闭分部集合 [0,1] ,剩余分部为 [2] 。
  • 关闭分部集合 [1,2] ,剩余分部为 [0] 。
  • 关闭分部集合 [0,2] ,剩余分部为 [1] 。
  • 关闭分部集合 [0,1,2] ,关闭后没有剩余分部。
    总共有 5 种可行的关闭方案。
    示例 2:
    在这里插入图片描述
    输入:n = 3, maxDistance = 5, roads = [[0,1,20],[0,1,10],[1,2,2],[0,2,2]]
    输出:7
    解释:可行的关闭分部方案有:
  • 关闭分部集合 [] ,剩余分部为 [0,1,2] ,它们之间的最远距离为 4 。
  • 关闭分部集合 [0] ,剩余分部为 [1,2] ,它们之间的距离为 2 。
  • 关闭分部集合 [1] ,剩余分部为 [0,2] ,它们之间的距离为 2 。
  • 关闭分部集合 [0,1] ,剩余分部为 [2] 。
  • 关闭分部集合 [1,2] ,剩余分部为 [0] 。
  • 关闭分部集合 [0,2] ,剩余分部为 [1] 。
  • 关闭分部集合 [0,1,2] ,关闭后没有剩余分部。
    总共有 7 种可行的关闭方案。
    示例 3:

输入:n = 1, maxDistance = 10, roads = []
输出:2
解释:可行的关闭分部方案有:

  • 关闭分部集合 [] ,剩余分部为 [0] 。
  • 关闭分部集合 [0] ,关闭后没有剩余分部。
    总共有 2 种可行的关闭方案。
class Solution {
    
    
public:
    int e[20][20];
    int dis[20][20];
    int numberOfSets(int n, int lim, vector<vector<int>>& roads) {
    
    
        int rt=0;
        memset(e,0x3f,sizeof(e));
        for(auto &p:roads)
        {
    
    
            int u=p[0],v=p[1],w=p[2];
            e[v][u]=e[u][v]=min(e[u][v],w);
        }
        for(int i=0;i<n;i++) e[i][i]=0;
        for(int s=0;s<1<<n;s++)
        {
    
    
            memcpy(dis,e,sizeof(dis));
            for(int k=0;k<n;k++) if(s&1<<k)
                for(int i=0;i<n;i++) if(s&1<<i)
                    for(int j=0;j<n;j++) if(s&1<<j)
                        dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
            for(int i=0;i<n;i++) if(s&1<<i)
                for(int j=0;j<n;j++) if(s&1<<j)
                    if(dis[i][j]>lim) goto fail;
            //cout<<"suc "<<s<<endl;
            rt++;
            fail:;
        }
        return rt;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_42725437/article/details/134903537