刺客信条

刺客信条

https://ac.nowcoder.com/acm/contest/6607/D

bfs/dfs/dijkstra +优先队列

起初看到这个题目我就想着一定是一个bfs的题,后面看大佬们的题解,发现大家都是用的dijkstra算法去做,因为求的是最短路嘛,但是因为这个题目的特殊性,dfs,bfs也可以用来求解最短路径,所以我就想每种方法都用一次

解法一:BFS+优先队列

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100;
char c[maxn][maxn];
int sx, sy, ex, ey, n, m;
int d[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int vis[maxn][maxn], b[maxn][maxn];
struct node
{
   int x, y, d;
   node(int xx, int yy, int dd) : x(xx), y(yy), d(dd) {}
   bool operator<(const node xx) const
   {
      return d > xx.d;
   }
};
int bfs(int x, int y)
{
   priority_queue<node> q;
   q.push(node(x, y, 0)); //首先把起点放入队列
   vis[x][y] = 1;
   while (!q.empty())
   {
      node xx = q.top();
      q.pop();
      if (xx.x == ex && xx.y == ey) //如果遇到了终点那么就返回当前距离
         return xx.d;
      for (int i = 0; i < 4; ++i) //依次遍历该点的上下左右节点
      {
         int nx = xx.x + d[i][0];
         int ny = xx.y + d[i][1];
         if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]) //判断边界
         {
            int h = xx.d + b[nx][ny]; //当前距离加上下一个的距离
            vis[nx][ny] = 1;
            q.push(node(nx, ny, h));
         }
      }
   }
}
int main()
{
   while (~scanf("%d%d", &n, &m))
   {
      for (int i = 1; i <= n; ++i)
         for (int j = 1; j <= m; ++j)
         {
            scanf(" %c", &c[i][j]); //这是一个小技巧,防止换行符和空格符号的干扰
            if (c[i][j] == 'S')
               sx = i, sy = j;
            else if (c[i][j] == 'E')
               ex = i, ey = j;
            else if (c[i][j] == 'A' || c[i][j] == 'B' || c[i][j] == 'C')
               b[i][j] = 100;
            else
               b[i][j] = c[i][j] - '0';
         }
      printf("%d\n", bfs(sx, sy));
   }
}

解法二:dfs

其实dfs的代码思路和bfs差不多,一个用队列一个用递归

#include <bits/stdc++.h>
using namespace std;
int a[100][100], vis[100][100];
int sx, sy, ex, ey, n, m;
int inf = 0x3f3f3f3f;
int d[4][2] = {-1, 0, 1, 0, 0, -1, 0, 1};
int xx[4] = {-1, 1, 0, 0}, yy[4] = {0, 0, -1, 1};
char c;
void dfs(int x, int y, int sum)
{
   if (x == ex && y == ey)
   {
      inf = min(sum, inf);
      return;
   }
   if (sum >= inf)
      return;
   for (int i = 0; i < 4; ++i)
   {
      int nx = x + d[i][0];
      int ny = y + d[i][1];
      if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny])
      {
         vis[nx][ny] = 1;
         dfs(nx, ny, sum + a[nx][ny]);
         vis[nx][ny] = 0;
      }
   }
}
int main()
{
   scanf("%d%d", &n, &m);
   for (int i = 1; i <= n; ++i)
      for (int j = 1; j <= m; ++j)
      {
         cin >> c;//c++输入语言默认是不输入空格和回车的
         if (c == 'S')
            sx = i, sy = j;
         else if (c == 'E')
            ex = i, ey = j;
         else if (c == 'A' || c == 'B' || c == 'C')
            a[i][j] = 100;
         else
            a[i][j] = c - '0';
      }
   dfs(sx, sy, 0);
   printf("%d\n", inf);
}

解法三:Dijkstra+堆优化

二维数组转一维然后跑一次dijkstra

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e3 + 7;
int n, m;
int map1[100][100];
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
struct node
{
    int e, w, dis;
    bool operator<(const node &a) const
    {
        return w > a.w;
    }
};
vector<node> w[maxn];
priority_queue<node> q;
int dis[maxn], vis[maxn];
void Dijkstra(int s)
{
    memset(dis, inf, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    node t1, t2;
    t1.e = s;
    t1.w = 0;
    dis[s] = 0;
    q.push(t1);
    while (!q.empty())
    {
        t1 = q.top();
        q.pop();
        if (vis[t1.e])
            continue;
        vis[t1.e] = 1;
        for (int i = 0; i < w[t1.e].size(); i++)
        {
            int v = w[t1.e][i].e;
            if (!vis[v] && dis[t1.e] + w[t1.e][i].w < dis[v])
            {
                dis[v] = dis[t1.e] + w[t1.e][i].w;
                t2.e = v;
                t2.w = dis[v];
                q.push(t2);
            }
        }
    }
}
int main()
{
    while (~scanf("%d%d", &n, &m))
    {
        int s, e;
        char c;
        int end = (n - 1) * m + m - 1;
        for (int i = 0; i <= end; i++)
        {
            dis[i] = inf;
            vis[i] = 0;
            w[i].clear();
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
            {
                cin >> c;
                if (c == 'A' || c == 'B' || c == 'C')
                    map1[i][j] = 100;
                else if (c == 'S')
                {
                    map1[i][j] = 0;
                    s = i * m + j;
                }
                else if (c == 'E')
                {
                    map1[i][j] = 0;
                    e = i * m + j;
                }
                else
                    map1[i][j] = c - '0';
            }
        node t;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                for (int k = 0; k < 4; k++)
                {
                    int x = i + dir[k][0];
                    int y = j + dir[k][1];
                    if (x < 0 || x >= n || y < 0 || y >= m)
                        continue;
                    t.e = x * m + y;
                    t.w = map1[x][y];
                    w[i * m + j].push_back(t);
                }
        Dijkstra(s);
        printf("%d\n", dis[e]);
    }
    return 0;
}
牛客课后习题题解 文章被收录于专栏

等待蜕变

全部评论

相关推荐

避坑恶心到我了大家好,今天我想跟大家聊聊我在成都千子成智能科技有限公司(以下简称千子成)的求职经历,希望能给大家一些参考。千子成的母公司是“同创主悦”,主要经营各种产品,比如菜刀、POS机、电话卡等等。听起来是不是有点像地推销售公司?没错,就是那种类型的公司。我当时刚毕业,急需一份临时工作,所以在BOSS上看到了千子成的招聘信息。他们承诺无责底薪5000元,还包住宿,这吸引了我。面试的时候,HR也说了同样的话,感觉挺靠谱的。于是,我满怀期待地等待结果。结果出来后,我通过了面试,第二天就收到了试岗通知。试岗的内容就是地推销售,公司划定一个区域,然后你就得见人就问,问店铺、问路人,一直问到他们有意向为止。如果他们有兴趣,你就得摇同事帮忙推动,促进成交。说说一天的工作安排吧。工作时间是从早上8:30到晚上18:30。早上7点有人叫你起床,收拾后去公司,然后唱歌跳舞(销售公司都这样),7:55早课(类似宣誓),8:05同事间联系销售话术,8:15分享销售技巧,8:30经理训话。9:20左右从公司下市场,公交、地铁、自行车自费。到了市场大概10点左右,开始地推工作。中午吃饭时间大约是12:00,公司附近的路边盖饭面馆店自费AA,吃饭时间大约40分钟左右。吃完饭后继续地推工作,没有所谓的固定中午午休时间。下午6点下班后返回公司,不能直接下班,需要与同事交流话术,经理讲话洗脑。正常情况下9点下班。整个上班的一天中,早上到公司就是站着的,到晚上下班前都是站着。每天步数2万步以上。公司员工没有自己的工位,百来号人挤在一个20平方米的空间里听经理洗脑。白天就在市场上奔波,公司的投入成本几乎只有租金和工资,没有中央空调。早上2小时,晚上加班2小时,纯蒸桑拿。没有任何福利,节假日也没有3倍工资之类的。偶尔会有冲的酸梅汤和西瓜什么的。公司的晋升路径也很有意思:新人—组长—领队—主管—副经理—经理。要求是业绩和团队人数,类似传销模式,把人留下来。新人不能加微信、不能吐槽公司、不能有负面情绪、不能谈恋爱、不能说累。在公司没有任何坐的地方,不能依墙而坐。早上吃早饭在公司外面的安全通道,未到上班时间还会让你吃快些不能磨蹭。总之就是想榨干你。复试的时候,带你的师傅会给你营造一个钱多事少离家近的工作氛围,吹嘘工资有多高、还能吹自己毕业于好大学。然后让你早点来公司、无偿加班、抓住你可能不会走的心思进一步压榨你。总之,大家在找工作的时候一定要擦亮眼睛,避免踩坑!———来自网友
qq乃乃好喝到咩噗茶:不要做没有专业门槛的工作
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务