• P1359 租用游艇 && P3905 道路重建 ------Floyd算法


    P1359 租用游艇   原题链接https://www.luogu.org/problemnew/show/P1359

    P3905 道路重建   原题链接https://www.luogu.org/problemnew/show/P3905

    这两道题我觉得都是Floyd算法的应用,所以我就放在一块来写了,毕竟A这两道题的时间间隔比较短;

    P1359 租用游艇

    对于这个题,一开始被这个半矩阵惊到了-------主要是不知道这个矩阵是什么意思,过了好长时间(2min)才明白是到其他游艇的距离。

    我们去理解一下输入:

    输入半矩阵的代码:

        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                f[i][j]=read();        //从游艇i到游艇j的距离 
            }
        }

    然后我们要求的就是游艇1到游艇n的距离,也就是f[1][n],这里我们用Floyd算法就能轻松AC;

    注意一个小细节:

    题目中说:游客可在这些游艇出租站租用游艇,并在下游的任何一个游艇出租站归还游艇。

    这句话其实是说:游艇只会顺流而下,不会逆流而上!所以我们要特判一下,如果我们枚举的中间点k<=i,直接continue;

    OK上代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int read()
    {
        char ch=getchar();
        int a=0,x=1;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') x=-x;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            a=(a<<3)+(a<<1)+(ch-'0');
            ch=getchar();
        }
        return a*x;
    }
    int n;
    int f[201][201];
    int main()
    {
        n=read();
        for(int i=1;i<n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                f[i][j]=read();        //从i到j的距离 
            }
        }
        for(int k=1;k<=n;k++)          //Floyd算法 
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(k<=i) continue; //如果枚举的中间点k在游艇i的上游,直接跳出 
                    if(f[i][j]>f[i][k]+f[k][j])
                    f[i][j]=f[i][k]+f[k][j];
                }
            }
        }
        cout<<f[1][n];                 //最后的答案 
        return 0;
    }

    P3905 道路重建

    这个题其实不是很难,只是思路有些难想,我也是看了题解之后才想出来的:

    这个题要你求从A到B要修的最短道路,也就是说那些没有被炸毁的道路我们不用修,我们可以将这些道路的权值赋为0,这样Floyd算法求出的最短路就是要修的最短道路,看代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int read()                           //读入优化 
    {
        char ch=getchar();
        int a=0,x=1;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') x=-x;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            a=(a<<3)+(a<<1)+(ch-'0');
            ch=getchar();
        }
        return a*x;
    }
    int n,m,d,f[101][101],vis[101][101]; //f数组存图,vis数组存哪条路被炸了 
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
           for(int j=1;j<=n;j++)
              f[i][j]=1e9,vis[i][j]=0;   //初始化 
        for(int i=1;i<=m;i++)
        {
            int u=read();
            int v=read();
            int w=read();
            f[u][v]=w;                   //注意建双向图 
            f[v][u]=w;
        }
        d=read();
        for(int i=1;i<=d;i++)
        {
            int u=read();
            int v=read();
            vis[u][v]=1;                 //表示u到v这条路被炸了 
            vis[v][u]=1;
        }
        for(int i=1;i<=n;i++)
           for(int j=1;j<=n;j++)
              if(vis[i][j]==0&&f[i][j]<1e9) //如果这条路没被炸,并且连通,那么将权值设为0 
                 f[i][j]=0;
        int s=read();
        int end=read();
        for(int k=1;k<=n;k++)            //Floyd算法模板 
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(f[i][k]+f[k][j]<f[i][j])
                    f[i][j]=f[i][k]+f[k][j];
                }
            }
        }
        cout<<f[s][end];                 //起点到终点的最短修的道路 
        return 0;
    }
  • 相关阅读:
    DevExpress的GridControl的实时加载数据解决方案(取代分页)
    WinForm程序虚拟分页(实时加载数据)
    C#使用反射特性构建访问者模式
    WinApi学习笔记内存的复制,填充,输出等操作
    PL/SQL学习笔记程序包
    WinApi学习笔记创建进程
    PL/SQL学习笔记触发器
    WinApi学习笔记获取光驱中的信息
    WinApi学习笔记读写文件
    不通过配置文件启动WCF服务
  • 原文地址:https://www.cnblogs.com/xcg123/p/11003889.html
Copyright © 2020-2023  润新知