Problem B : Sailing

原博客:http://blog.csdn.net/wyxeainn/article/details/72853263
Problem B : Sailing

From: DHUOJ, 2017060302
Submit (Out of Contest)
Time Limit: 1 s
Description
Handoku is sailing on a lake at the North Pole. The lake can be considered as a two-dimensional square plane containing N × N blocks, which is shown in the form of string containing ‘*’ and ‘#’ on the map.
* : a normal block;
# : a block containing pack ice.

Handoku is at (1, 1) initially, and his destination is (N, N). He can only move to one of the four adjacent blocks. Sailing around pack ice is dangerous and stressful, so he needs power to remain vigilant. That means if he moves from a ‘*’ block to a ‘#’ block or moves from a ‘#’ block to any another block, he needs to consume 1 unit power. In other cases, he can enjoy the scene on his boat without consuming any power.

Now Handoku wants to know how many units power will be consumed at least during his sailing on the lake.

Input
There are several test cases (no more than 20).
For each test case, the first line contains a single integer N (3 ≤ N ≤ 50), denoting the size of the lake. For the following N lines, each line contains a N-length string consisting of ‘*’ and ‘#’, denoting the map of the lake.

Output
For each test case, output exactly one line containing an integer denoting the answer of the question above.

Sample Input

3
**#
**#
*#*
3
##*
#*#
###
4
**##
#**#
##**
###*

Sample Output

2
4
0

题目意思:
给出一个N*N的地图,起点(1,1),终点(n,n),每次只可以向四个方向走一个格子,地图只由两个字符组成 ‘*’ 和 ‘#’。
从字符 ‘*’ 走到字符’#’需要花费1秒时间,从字符’#’走到其他位置(无论那个位置字符是什么)也要花费1秒时间。其他
情况不花费时间。求从(1,1)走到(n,n)花费的最小时间。
解题思路:
这个题,上来第一个做的,感觉特别简单,BFS+优先队列然后标记每个点只走一次就行了,结果WA了4次,出师不利呀,又看了榜单,发现
大家都在WA,所以先隔过去了,但是最后感觉没有别的题能写出来了,又看到B题WA了好多次的人都A出来了,所以拐回去做。原来我的思路
是走过的地方不能再走,这样写每次提交都WA,就想了难道还能走回头路?但是觉得自己已经用了优先队列,感觉没道理WA。但是事实上是
那样做行不通(还好这次我没钻牛角尖,平时做题觉得思路没问题的时候,自己都死活不愿意改代码,而且也换题做,一般都是WA到死),所
以就试了一下走回头路,原来vis数组刷成0,走过的都标1。为了走回头路,新的代码把vis刷成-1,然后对于走过的点,vis放置走到该点的最小时
间,这样走到一个点,如果这个点没有访问过,即对应的vis是-1,则该点一定要进队,然后vis变成到达该点的时间。对于已经当过的点,vis数组
里面存放的是它上一次到达这个点的最小时间,现在又到了这个点,如果时间比vis里面的时间短,则更新vis,该点再次入队。这样处理后就可以
AC了,但是我没想出这样的测试数据,希望看到博客的人帮我想一组走回头路时间更短的数据。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;

const int maxn = 55;
char Map[maxn][maxn];///存图的
int vis[maxn][maxn];///走到该点的最小时间
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}}; ///搜索方向上右下左
int n;
struct pos
{
    int x;
    int y;
    int power;
    friend bool operator < (pos a,pos b)///运算符函数(今天学的'17-6-6')
    {
        return a.power>b.power; ///"<"为从大到小排列,">"为从小到大排列
    }
};

///遍历地图
int bfs()
{
    pos cur,nex;
    cur.x = 1;
    cur.y = 1;
    cur.power = 0;
    vis[cur.x][cur.y] = cur.power;
    ///初始第一个pos的值
    priority_queue<pos>qu;///(结构体) 优先队列(普通的优先队列是从大到小排)上面的函数是为了让他按照power的值从小到大排序
    qu.push(cur);
    while(!qu.empty())
    {
        cur = qu.top();///返回队首元素
        qu.pop();/// 弹出队列的第一个元素(队顶元素),注意此函数并不返回任何值

        if(cur.x == n && cur.y == n)
            return cur.power;

        for(int i = 0; i < 4; i++)
        {
            nex.x = cur.x + dir[i][0];
            nex.y = cur.y + dir[i][1];
            nex.power = cur.power;
            if(nex.x<1||nex.x>n||nex.y<1||nex.y>n) continue;///边界
            if(Map[cur.x][cur.y]=='*')
            {
                if(Map[nex.x][nex.y]=='#')///'*'到'#';nex.power++;
                    nex.power++;
            }
            else
            {
                nex.power++;///'#';nex.power++;
            }
            if(vis[nex.x][nex.y]==-1)///如果这一点没有时间,直接将nex.power的值赋给 vis
            {
                vis[nex.x][nex.y] = nex.power;
                qu.push(nex);///进队列
            }
            else
            {
                if(nex.power<vis[nex.x][nex.y])
                {
                    vis[nex.x][nex.y] = nex.power;///将较小的一个赋给 VIS,这样就可以求出到每一个的点最小时间并赋给VIS记录
                    qu.push(nex);///进队列
                }
            }
        }
    }
    return -1;
}
///主函数没什么看头
int main()
{
    while(~scanf("%d",&n))
    {
        getchar();
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
            {
                scanf(" %c",&Map[i][j]);
            }
        memset(vis,-1,sizeof(vis));
        int ans = bfs();
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 内容概要 《计算机试卷1》是一份综合性的计算机基础和应用测试卷,涵盖了计算机硬件、软件、操作系统、网络、多媒体技术等多个领域的知识点。试卷包括单选题和操作应用两大类,单选题部分测试学生对计算机基础知识的掌握,操作应用部分则评估学生对计算机应用软件的实际操作能力。 ### 适用人群 本试卷适用于: - 计算机专业或信息技术相关专业的学生,用于课程学习或考试复习。 - 准备计算机等级考试或职业资格认证的人士,作为实战演练材料。 - 对计算机操作有兴趣的自学者,用于提升个人计算机应用技能。 - 计算机基础教育工作者,作为教学资源或出题参考。 ### 使用场景及目标 1. **学习评估**:作为学校或教育机构对学生计算机基础知识和应用技能的评估工具。 2. **自学测试**:供个人自学者检验自己对计算机知识的掌握程度和操作熟练度。 3. **职业发展**:帮助职场人士通过实际操作练习,提升计算机应用能力,增强工作竞争力。 4. **教学资源**:教师可以用于课堂教学,作为教学内容的补充或学生的课后练习。 5. **竞赛准备**:适合准备计算机相关竞赛的学生,作为强化训练和技能检测的材料。 试卷的目标是通过系统性的题目设计,帮助学生全面复习和巩固计算机基础知识,同时通过实际操作题目,提高学生解决实际问题的能力。通过本试卷的学习与练习,学生将能够更加深入地理解计算机的工作原理,掌握常用软件的使用方法,为未来的学术或职业生涯打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值