zoukankan      html  css  js  c++  java
  • P1364 医院设置(洛谷)

    题目描述:传送门

    思路实现:

      看见最短路径:我们可以联想到的算法有狄克斯特拉算法,弗洛伊德算法和bfs。实际上这道题目弗洛伊德算法比较合适,但此处作为一个bfs问题来求解。由于医院可能建立的点有1~n,因此分别以1~n为起点去进行bfs,分别求出最短路径,再从这些最短路径中挑选出最小的那条路径,该路径的起点则是医院的建立点。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 //虽然此处是树状结构,其实也能用邻接表的方式进行bfs,分别以每个结点当起点进行bfs
     5 //建树方式也可以,只不过麻烦,bfs前还得建棵树 
     6 
     7 //新思路解决结点所在深度问题:设计一个结构体,保存当前结点的下标和深度,当前结点更新:上一层结点深度+1 
     8 int minn=1<<30;
     9 int n=0;
    10 int mapp[105][105]={0};
    11 bool v[105];        //用于判断某个点是否被访问过 
    12 int w[105]={0};        //存人口数 
    13 int bfs(int index){    //index下标,
    14     memset(v,0,sizeof(v));
    15     int sum=0;
    16     int size=1;            //size表示的是当前层的结点数,每访问一个结点size--知道size减少到0代表当前层的结点全部已经遍历,此时深度step++ 
    17                         //因为只有遍历完当前层最右边的点后深度step才会加1,同时也才进入下一层 
    18     int temp=0;            //temp记录的是当前层的下一层的结点数,当size为0的时候,意味着进入下一层去遍历,
    19                         // 因此temp值赋给size,而temp情况重新累计下一层的结点数 
    20     queue<int> q;
    21     q.push(index);        //起点入队
    22     v[index]=1; 
    23     int step=1;            //记录bfs搜索层数 
    24     while(!q.empty()){ 
    25         int cur=q.front();        //cur是当前结点下标 
    26         q.pop();
    27         for(int i=1;i<=n;i++){
    28             if(mapp[cur][i]==0||v[i])    continue;
    29             sum+=w[i]*step;
    30             q.push(i);        //入队
    31             v[i]=1; 
    32             
    33             if(size>0){
    34                 temp++;
    35             }
    36         }
    37         size--;
    38         if(size==0){
    39             size=temp;
    40             temp=0;            //又重新清0 
    41             step++;
    42         }
    43     }
    44     return sum;
    45 } 
    46 int main(){
    47     cin>>n;
    48     for(int i=1;i<=n;i++){
    49         int v,u;
    50         cin>>w[i];
    51         cin>>u>>v;
    52         
    53         //再输入0的情况下也标了1 
    54         if(u) mapp[i][u]=1;    //表示有连接 
    55         if(u) mapp[u][i]=1;    //无向图 所以对称
    56         if(v) mapp[i][v]=1;
    57         if(v) mapp[v][i]=1;
    58     }
    59 
    60     for(int i=1;i<=n;i++){    //设每次bfs的起点是医院位置         
    61         minn=min(minn,bfs(i));
    62     }
    63     cout<<minn;
    64     return 0;
    65 }

     第二种bfs解法:只是将层数与顶点进行绑定方便操作

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<queue>
    using namespace std;
    
    //这题是求最短距离问题  很适合bfs的使用
    //并且求医院的建筑点 应该以每个节点为医院站点试试
    int n;
    int mapp[105][105]={0}; //用于储存连接关系
    int color[105];         //标记
    int nodevalue[105];     //储存节点的数值
    int dis[105];       //dis[i]表示节点为i作为医院建造点的总距离
    int temp=0;
    typedef struct node{
        int code;       //编号
        int l;          //该点所在层数
    }N;
    
    void bfs(int k){
        color[k]=1;
        queue<N> q;
        N cur,next;
        cur.code=k;
        cur.l=0;
        q.push(cur);      //编号为k的点入队
    
        while(!q.empty()){
            next=q.front();
            q.pop();
    
            // cout<<next.code<<endl;
            for(int i=1;i<=n;i++){
                if((mapp[i][next.code]||mapp[next.code][i])&&!color[i]){        //i点不能被访问过
                    temp+=nodevalue[i]*(next.l+1);
                    color[i]=1;         //记得标记
                    N t;
                    t.code=i;
                    t.l=next.l+1;      //代表上一层加1
                    q.push(t);
                }
            }
        }
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>nodevalue[i];
            int a,b;
            cin>>a>>b;
            if(a!=0){
                mapp[i][a]=1;       //无向
                mapp[a][i]=1;
            }
            if(b!=0){
                mapp[i][b]=1;
                mapp[b][i]=1;
            }
        }
    
        
        for(int i=1;i<=n;i++){
            memset(color,0,sizeof(color));
            temp=0;
            bfs(i);
            dis[i]=temp;
        }
        sort(dis+1,dis+n+1);        //对dis[1]~dis[n]排序
        cout<<dis[1];
        return 0;
    }
  • 相关阅读:
    勤于思考:jquery.getJSON的缓存问题的解决方法
    步步为营:SQLServer查询随机不相同的记录插入临时表
    勤于思考:Asp.Net MVC Html.TextBoxFor日期格式化
    勤于思考:Excel写公式换算单元格求积等
    步步为营:ASP.NET MVC中Area分层模块处理大解密
    步步为营:因为数据库正在使用,所以无法获得对数据库的独占访问权
    勤于思考:从客户端中检测到有潜在危险的 Request.Form 值
    Android天天数钱游戏项目源码
    iOS猜拳游戏源码
    李开复:AlphaGo 若打败了世界冠军,意味着什么?
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12735499.html
Copyright © 2011-2022 走看看