[YZOJ]P1022--Age(2)

题目原文(YZOJ)

题目描述
周园和楼主在网络上展开了AGE大战。激战之后楼主大败,拼死留下了一个农民和几个爆破兵。楼主决定用他的老战术–逃到一个角落重新发展。可是由于周园的建筑建得很密,楼主的农民无法直接到达目的的。于是只好动用爆破兵破坏几个建筑。一个爆破兵只能破坏一个建筑。由于周园的建筑很有建筑美,呈网格型,所以楼主走的路径其实是一个折线。 现给你一个MN的矩阵(包括空地和房屋,一个房屋占一格)。起点为:(1,1);终点为:(M,N)。求楼主的农民到终点最少需要多少步(起点不算,终点算一步)。若无法达到,则输出: ‘LouZhu Will Be Dead.’。(1,1) 和(M,N)上必没有建筑。
输入格式
第一行为M N P表示M行N列的矩阵和拥有的爆破兵个数。 以下行为M
N的矩阵,0表示无建筑,1表示有建筑 M N P X11 X22……X2n … … Xm1 Xm2….Xmn
输出格式
农民到达目的地最少的步数。
样例输入
4 5 1
0 0 1 1 0
1 1 1 1 1
0 1 0 0 0
0 0 0 1 0
样例输出
9
数据规模与约定
0<M,N<=100
0<=P<=500

一,题面简化
这道题就是一道类似于走迷宫的题目,然后还有一个强行走过障碍的炸弹技能,但是使用次数有限,求最短到达目的地距离,还要判断是否不能到达
二,思路分析
其实最初看到这道题的时候,我们可以搭建一个DFS的迷宫搜索框架,具体过程不细说,基础迷宫代码
但是,这道题数据如果单单靠DFS是过不去的(吧),所以我们加入记忆化搜索。
怎么加呢?因为每次每个格子会变化的信息有:横坐标,纵坐标,当前炸弹数。所以我们可以得到一个三维变量anser[i][j][k],表示当楼主在格子(i,j)上,且炸弹还有k个时走过了没,避免重复
三,完整代码

#include<iostream>
#include<cstdio>
#define MAXX 1000010
#define MAX 110
using namespace std;
int p,n,m;
int a[MAX][MAX];
bool anser[MAX][MAX][510];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
struct node{
	int x,y;//坐标
	int boom;//炸弹
	int anss;//步数统计 
}s[MAXX];
void bfs(){
	int head=0,tail=1,xx,yy;
	s[1].x=s[1].y=1;
	s[1].boom=p;
	s[1].anss=0;
	head=0;tail=1;
	while(head<tail){
		head++;
		if(s[head].x==n&&s[head].y==m){
			printf("%d\n",s[head].anss);
			return ;
		} 
		for(int i=0;i<=3;i++){
			xx=dx[i]+s[head].x;
			yy=dy[i]+s[head].y;
			if(xx<1||yy<1||xx>n||yy>m) continue;//越界
			int boomn;
			boomn=s[head].boom-a[xx][yy];//相当于查看是否需要炸弹
			if(anser[xx][yy][boomn]==0&&boomn>=0){
			//有这个状态且炸弹够炸
				s[++tail].x=xx;//存入队列
				s[tail].y=yy;
				s[tail].boom=boomn;
				s[tail].anss=s[head].anss+1;
				anser[xx][yy][boomn]=1;
		}
		}
	}
	printf("LouZhu Will Be Dead.\n");
	return ;
}
int main(){
	int i,j;
	scanf("%d%d%d",&n,&m,&p);
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++)
			scanf("%d",&a[i][j]);
	bfs();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值