码迷,mamicode.com
首页 > 其他好文 > 详细

2019 上半年 南昌网络赛

时间:2019-09-09 23:05:55      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:return   out   dijkstra   算法   jks   printf   更新   blank   stream   

B、Fire-Fighting Hero

图论题-单源最短路径:添加一个顶点,连接各个救火团队所在的救火点,路径长度均设为 0,设该顶点为源,即变成了单源最短路径问题。使用两次Dijkstra算法可求出两个最短路径 的最大值。比较时将救火团队的乘以C进行比较可避免分数操作。

#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
#define INF 0x3f3f3f3f
using namespace std;
int vis[1005],way[1005][1005],dis[1005],a[1005];
int n,m;
//vis[i]标记已经处理过的点,dis[j]记录起点s到点j最近的距离,way[][]表示路径关系
void init()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==j)
                way[i][j]=0;
            else
                way[i][j]=INF;
        }
    }
}
void Dijkstra(int s)
{
    int mn;
    for (int i = 1; i <= n; i++)//初始化
    {
        vis[i] = 0;
        dis[i] = way[s][i];
    }
    vis[s] = 1;
    for (int i = 1; i <= n; i++)
    {
        int u;
        mn = INF;
        u = -1;
        for (int j = 1; j <= n; j++)//找出离初始起点s直接距离最近的点,记录下标和最近距离
        {
            if (vis[j] == 0 && dis[j] < mn)
            {
                u = j;
                mn = dis[j];
            }
        }
        if (u == -1)//如果没有找到
            break;
        vis[u] = 1;
        for (int j = 1; j <= n; j++)//更新
        {
            if (vis[j] == 0)
            {
                if (dis[u] + way[u][j] < dis[j])
                    dis[j] = dis[u] + way[u][j];
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int s,k,c;
        scanf("%d%d%d%d%d",&n,&m,&s,&k,&c);//n是起火点的个数,m是边数,s是消防英雄所在位置,k个消防队,c是系数
        for(int i=0;i<k;i++)
            scanf("%d",&a[i]);
        init();
        for(int i=0;i<m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(way[x][y]>z)
            {
                way[x][y]=z;
                way[y][x]=z;
            }
        }
        Dijkstra(s);
        int ans1=0;
        for(int i=1;i<=n;i++)//消防英雄到各个起火点距离的最大值
            ans1=max(ans1,dis[i]);
        
        for(int i=0;i<k;i++)//把n个消防队连接起来,变成一个点
        {
            for(int j=0;j<k;j++)
                way[a[i]][a[j]]=0;
        }
        Dijkstra(a[0]);
        int ans2=0;
        for(int i=1;i<=n;i++)//遍历消防队到各个起火点距离的最大值
            ans2=max(ans2,dis[i]);
    
        if(ans1>ans2*c)
            printf("%d\n",ans2);
        else
            printf("%d\n",ans1);
    }
    return 0;
}

 

E、Magic Master

题意:有n张连续的牌,一次操作m张牌,q次询问,每次询问数字为x的牌在洗牌之前的位置。

操作是:先把n张牌洗牌之后放在桌面上,每次从桌面拿一张牌到手中,拿完一张牌之后,把桌面上面的m张牌一次放到最底下,重复操作,直到拿完桌面上的所有牌;

最后手上的牌的顺序是依次递减的

 

题解:用队列逆向模拟还原即可:从第n张牌开始,把第n张牌从手里放到桌面之后,把最底下的牌放到最顶上,然后把第n-1张牌放到桌面,再把最底下的牌放到最顶上,直到手里没有牌

#include<iostream>
#include<queue>
using namespace std;

int n,m,t,k;
int b[40000005];
int q[40000005];
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>k;
        queue<int>p;
        for(int i=0;i<k;i++)
            cin>>q[i];
        for(int i=n;i>=1;i--)
        {
            if(!p.empty())
            {
                for(int j=1;j<=m;j++)
                {
                    int top=p.front();
                    p.pop();
                    p.push(top);
                }
            }
            p.push(i);
        }
        for(int i=n;i>=1;i--)
        {
            int now=p.front();
            b[i]=now;
            p.pop();
        }
    
        for(int i=0;i<k;i++)
            cout<<b[q[i]]<<endl;
    }

    return 0;
}

 

2019 上半年 南昌网络赛

标签:return   out   dijkstra   算法   jks   printf   更新   blank   stream   

原文地址:https://www.cnblogs.com/-citywall123/p/11494569.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!