牛客-2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛-A-PUBG

31 篇文章 0 订阅
6 篇文章 0 订阅

链接:https://www.nowcoder.com/acm/contest/118/A
来源:牛客网

最近,喜爱ACM的PBY同学沉迷吃鸡,无法自拔,于是又来到了熟悉的ERANGEL。
经过一番搜寻,PBY同学准备动身前往安全区,但是,地图中埋伏了许多LYB,PBY的枪法很差,
希望你能够帮他找到一条路线,每次只能向上、下、左、右移动,尽可能遇到较少的敌人。

输入描述:
题目包含多组测试,请处理到文件结束;
第一行是一个整数n,代表地图的大小;
接下来的n行中,每行包含n个整数a,每个数字a代表当前位置敌人的数量;
1 < n <= 100,1 <= a <= 100,-1代表当前位置,-2代表安全区。

输出描述:
对于每组测试数据,请输出从当前位置到安全区所遇到最少的敌人数量,每个输出占一行。


示例1
输入
5
6 6 0 -2 3
4 2 1 2 1
2 2 8 9 7
8 1 2 1 -1
9 7 2 1 2
输出
9

示例2
输入
5
62 33 18 -2 85
85 73 69 59 83
44 38 84 96 55
-1 11 90 34 50
19 73 45 53 95
输出
173

思路:最短路||BFS

1. 最短路:可以将图转换成一个个点,在用Spfa算法来求解

2. BFS: 可从起点开始宽度搜索,对于搜过的点放入 优先队列 Q中,对于Q中 路径小的先出队列,因此这样可以保证最先搜到终点时即为最短路径。

Code 1:

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

const int MAX_N=10005;
const int INF=1e9;
int n,m;
int a[MAX_N];
vector<int> G[MAX_N];
bool book[MAX_N];
int dist[MAX_N];


bool Spfa(int S);
int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n){
		m=0;
		memset(a,0,sizeof(a));
		memset(book,0,sizeof(book));
		for(int i=0;i<MAX_N;++i)
			G[i].clear();
		int S,T;
		for(int i=0;i<n;++i)
			for(int j=1;j<=n;++m,++j)
			{
				cin>>a[m];
				if(a[m]==-1){
					a[m]=0;	S=m;
				}else	if(a[m]==-2){
					a[m]=0;	T=m;
				}
			}
		for(int i=0;i<m;++i)
		{
			if(i-n>=0)	G[i].push_back(i-n);
			if(i+n<=m)	G[i].push_back(i+n);
			if(i%n)	G[i].push_back(i-1);
			if((i+1)%n)	G[i].push_back(i+1);
		}
		Spfa(S);
		cout<<dist[T]<<endl;
	}
	
	return 0;
}

bool Spfa(int S)
{
    int i,t,k;
    queue<int>  Q;
    for(int i=0;i<MAX_N;++i)
    {
    	book[i]=false;
    	dist[i]=INF;
	}
    Q.push(S);
    book[S]=true;
    dist[S]=0;
    while(Q.size())
    {
        t=Q.front();	Q.pop();
		book[t]=false;
		for(auto c:G[t])
		{
			if(dist[c]>dist[t]+a[c]){
				dist[c]=dist[t]+a[c];
				if(book[c]==false){
					Q.push(c);
					book[c]=true;
				}
			}
		}
    }
    return true;
}

Code 2:

//优先搜索路径小的点 
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;

struct node{
    int x;
	int y;
	int sum;
    bool operator<(const node &p)const{
        return sum>p.sum;
    }
};
const int MAX_N=105;
const int a[4][2]={-1,0, 1,0, 0,-1, 0,1};
int n,ans;
int G[MAX_N][MAX_N];
bool boo[MAX_N][MAX_N];

void BFS(node S);
int main(){
	ios::sync_with_stdio(false);
	node S;
    while(cin>>n){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
            	cin>>G[i][j];
            	if(G[i][j]==-1){
                    S.x=i;	S.y=j;	S.sum=0;
                }
			}
		BFS(S);
        cout<<ans<<endl;
    }
    return 0;
}

void BFS(node S)
{
    priority_queue<node> Q;
	memset(boo,0,sizeof(boo));
	ans=-1;
    Q.push(S);
    boo[S.x][S.y]=true;
    while(!Q.empty()&&ans==-1){
        node now=Q.top();
        Q.pop();
        node next;
        for(int i=0;i<4;i++)
		{
            next.x=now.x+a[i][0];	next.y=now.y+a[i][1];
            next.sum=now.sum+G[next.x][next.y];
            if(next.x>=1&&next.x<=n&&next.y>=1&&next.y<=n&&!boo[next.x][next.y]){
                if(G[next.x][next.y]==-2){
                    ans=now.sum;	break;
                }
                Q.push(next);
                boo[next.x][next.y]=true;
            }
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值