zoukankan      html  css  js  c++  java
  • p1221网络布线(最小生成树 Prim(普里母)算法) p1222 Watering Hole

    描述 Description
    农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场。当然,他需要你的帮助。约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场。为了用最小的消费,他想铺设最短的光纤去连接所有的农场。你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案。每两个农场间的距离不会超过100000

    输入格式 Input Format
    第一行: 农场的个数,N(3<=N<=100)。
    第二行..结尾: 后来的行包含了一个N*N的矩阵,表示每个农场之间的距离。当然,对角线将会是0,因为不会有线路从第i个农场到它本身。


    输出格式 Output Format
    只有一个输出,其中包含连接到每个农场的光纤的最小长度。

    样例输入 Sample Input

    4
    0 4 9 21
    4 0 8 17
    9 8 0 16
    21 17 16 0

    样例输出 Sample Output

    28

    这道题直接从第一个点开始作为光纤的起点链接每一个牧场,然后记录在哪个牧场时所用光纤最短。

    然后使用prim算法,现将第一个牧场添加进入到图中,然后枚举每条边,寻找现在能到达的边中的最短的那条。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<iomanip>
    using namespace std;
    int a[1100][1100];
    int dis[11000];
    bool vis[11000];
    int main()
    {
        int n;
        cin>>n;
        memset(a,10,sizeof(a));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cin>>a[i][j];
            }
        }
        int minn1=100000,sum,sumn;
        for(int k=1;k<=n;k++)
        {
            memset(dis,10,sizeof(dis));
            for(int i=1;i<=n;i++)
                dis[i]=a[k][i];
            memset(vis,0,sizeof(vis));
            vis[k]=1;
            sumn=0;sum=0;
            for(int i=2;i<=n;i++)
            {
                int minn=a[0][0],c=0;
                for(int j=1;j<=n;j++)
                    if((!vis[j])&&(dis[j]<minn))
                    {
                        minn=dis[j];
                        c=j;
                    }
                vis[c]=1;
                sumn+=minn;
                for(int j=1;j<=n;j++)
                {
                    if((a[c][j])<dis[j]&&(!vis[j]))
                        dis[j]=a[c][j];
                }
                
            }
            for(int j=1;j<=n;j++)
            {
                sum+=dis[j];
            }
            if(sum<minn1)
            {
                minn1=sum;
            }
        }
        cout<<sum<<endl;
        return 0;
    }

    其实sumn这个变量记录的就是从起始点牧场到达各个牧场的最短距离,枚举完后sumn=sum的。

      Watering Hole

    题目:

    Farmer John希望把水源引入他的N (1 <= N <= 300) 个牧场,牧场的编号是1~N.他将水源引入某个牧场的方法有两个,一个是在牧场中打一口井,另一个是将这个牧场与另一个已经有水源的牧场用一根管道相连.
    在牧场i中打井的费用是W_i (1 <= W_i <= 100000).
    把牧场i和j用一根管道相连的费用是P_ij (1 <= P_ij <= 100000, P_ij = P_ji, P_ii = 0).
    请你求出Farmer John最少要花多少钱才能够让他的所有牧场都有水源.

    输入格式 Input Format 
       * 第1行: 一个正整数N.
     * 第2~N+1行: 第i+1行包含一个正整数W_i.
     * 第N+2~2N+1行: 第N+1+i行包含N个用空格分隔的正整数,第j个数表示P_ij.
       输出格式 Output Format 
       总共有四个牧场.在1号牧场打一口井需要5的费用,在2或者3号牧场打井需要4的费用,在4号牧场打井需要3的费用.在不同的牧场间建立管道需要2,3或4的费用.

    样例输入 Sample Input     

    4

    5

    4

    4

    3

    0 2 2 2

    2 0 3 3

    2 3 0 4

    2 3 4 0     

     样例输出 Sample Output     

    9

    输出数据解释 Farmer John需要在4号牧场打一口井,然后把所有牧场都用管道连到1号牧场上,总共的花费是3+2+2+2=9.     

      时间限制 Time Limitation     1s   

    这道题直接直接从打井花费最少的地方开始打井,然后让用管子讲打井的牧场和其他牧场连通,比如:你在i花费3打了一口井要连到j牧场,连到j牧场要花费6,而在j牧场打一口井只用花费4,那就用在j牧场打井代替连接i到j,这样才会使花费最少.最后还是用Prim算法进行求最少花费。

    代码如下:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    using namespace std;
    int a[310][310];
    int dis[1100];
    bool vis[1100];
    int sumn;
    int main()
    {
        //freopen("add.in","r",stdin);
        //freopen("add.out","w",stdout);
        memset(vis,false,sizeof(vis));
        memset(dis,10,sizeof(dis));
        int n;
        memset(a,10,sizeof(a));
        cin>>n;
        int minn1=100000,s;
        for(int i=1;i<=n;i++)
        {
            cin>>dis[i];
            if(dis[i]<minn1)
            {
                minn1=dis[i];
                s=i;
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cin>>a[i][j];
            }
        }
        sumn=0;
        sumn+=dis[s];
        for(int i=1;i<=n;i++) 
        {
            if(dis[i]>a[s][i])
                dis[i]=a[s][i];
        }
        vis[s]=1;
        for(int i=2;i<=n;i++)
        {
            int minn=9999999,c=0;
            for(int j=1;j<=n;j++)
                if((!vis[j])&&(dis[j]<minn))
                {
                    minn=dis[j];
                    c=j;
                }
            vis[c]=1;
            sumn+=minn;
            for(int j=1;j<=n;j++)
            {
                if((a[c][j]<dis[j])&&(!vis[j]))
                {
                    dis[j]=a[c][j];
                }
            }
        }
        cout<<sumn<<endl;
        return 0;
    }


     

  • 相关阅读:
    C#托盘图标
    线程相关整理
    Quartz.NET 快速入门
    (转)IE内存泄露,iframe内存泄露造成的原因和解决方案
    美化console.log的文本(转载)
    mongoDB学习资料整理
    EF7学习资料整理
    Oracle常用
    Node.js学习资料整理
    【大型网站技术实践】初级篇:借助Nginx搭建反向代理服务器(转)
  • 原文地址:https://www.cnblogs.com/lcyhaha/p/6402181.html
Copyright © 2011-2022 走看看