2017上海金马五校程序设计竞赛 B:Sailing

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单位能量,其他情况不消耗能量,问消耗的最小能量是多少。

解题思路:

用BFS+优先队列来做。但是要注意的是它的标记数组,走到的地方消耗的能量如果比下一次走到该地方消耗的能量大,那就要变成下一次走到该地消耗的能量。即标记数组记得是走到该地消耗的最小能量,不断刷新标记数组的值就好。



#include<iostream>
#include<string>
#include<string.h>
#include<sstream>
#include<queue>
using namespace std;
struct node
{
    int x,y,power;
    friend bool operator<(node a,node b)
    {
        return a.power>b.power;
    }
} s,e;
int n;
char a[51][51];
int vi[51][51];
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}}; //走的方向
void bfs()
{
    priority_queue<node>q;
    node t,x1;
    vi[0][0]=1;
    if (a[s.x][s.y]=='#')
        s.power+=1;
    q.push(s);
    while(!q.empty())
    {
        t=q.top();
        q.pop();
        for(int i=0; i<4; i++)
        {
            x1.y=t.y+dir[i][1];
            x1.x=t.x+dir[i][0];
            if(x1.x>=0&&x1.x<n&&x1.y>=0&&x1.y<n&&vi[x1.x][x1.y]==0)
            {

                vi[x1.x][x1.y]=1;
                if (a[x1.x][x1.y]=='*')
                {
                    x1.power=t.power;
                }
                else
                {
                    if (a[t.x][t.y]=='#')
                        x1.power=t.power+1;
                    else
                    x1.power=t.power+2;
                }
                if (x1.x==n-1&&x1.y==n-1)
                {
                    if(a[n-1][n-1]=='#')
                        x1.power--;
                    cout<<x1.power<<endl;
                    return ;
                }
                q.push(x1);
            }
        }
    }
}
int main()
{
    while(cin>>n)
    {
        memset(vi,0,sizeof(vi));
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
            {
                cin>>a[i][j];
            }
        s.x=0;
        s.y=0;
        s.power=0;
        bfs();
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值