FZU 2150

本文详细解析了一种草地图遍历算法,通过使用vector存储草的位置,再逐一枚举,利用计数器计算草的数量,当草数量归零时返回步数。此算法适用于n、m范围较小的情况,通过具体AC代码示例,展示了如何实现该算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

放火烧草,每次可选两个点放

题解: n,m范围非常小,所以先用vector存起来草的位置,在一个个枚举即可。然后用一个计数器,来计算草的数量,当草数量为0时,就返回步数。

(T了很多发,因为没有加vis判断访问)

AC 代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define ll long long 
#define up(i,a,n) for(int i=a;i<=n;i++)
#define down(i,a,n) for(int i=a;i>=n;i--)
#define pb push_back
const int maxn=15;
char Map[maxn][maxn];
bool vis[maxn][maxn];
bool vis1[maxn][maxn];
int _move[4][2]={0,1,0,-1,1,0,-1,0};
int n,m,granum,granum1;
struct node
{
	int x,y,cnt,granum;
	void ss(int x1,int y1,int cnt1){
		x=x1,y=y1;cnt=cnt1;
	}
};
bool check(int x,int y)
{
	if(Map[x][y]=='.'||x<1||x>n||y<1||y>m||!vis[x][y])return false;
	return true;
}
int bfs(node a,node b){
	queue<node>q;
	q.push(a);
	q.push(b);//入队 
	while(!q.empty())//一波一波一步一步走 
	{
		node ss=q.front();q.pop();
		if(vis[ss.x][ss.y])granum--;
		else continue;
		vis[ss.x][ss.y]=false;
		if(granum==0)return ss.cnt;
		ss.cnt++;
		up(i,0,3)
		{
			ss.x+=_move[i][0];
			ss.y+=_move[i][1];
			if(check(ss.x,ss.y))
			{
			q.push(ss);
			} 
			ss.x-=_move[i][0];
			ss.y-=_move[i][1];
		}
	}//走完后 
	return 999999;
}
int main()
{
	int t;
	scanf("%d",&t);
	for(int cas=1;cas<=t;cas++)
	{   vector<node>grass;//草地 
	    granum1=0;//用来记录草地的块数 
		scanf("%d%d",&n,&m);
		memset(Map,'\000',sizeof(Map));
		memset(vis1,true,sizeof(vis1));
		up(i,1,n)scanf("%s",Map[i]+1);//存图 
		up(i,1,n)
		{
			up(j,1,m)
			{
				if(Map[i][j]=='#')
				{
					node ss;
					ss.ss(i,j,0);
					grass.pb(ss);//草地进栈 
					granum1++;//草地块数+1 
				}
				else vis1[i][j]=false;//如果为‘.’,则不能走 
			}
		}
		if(granum1<=2){
		printf("Case %d: 0\n",cas);
		continue;
	    } //如果草地的块数小于等于2,直接输出0 
		int ans=999999;
	up(i,0,grass.size()-1)//枚举每个起点,进入bfs。 
	{
		for(int j=i;j<grass.size();j++)
		{
			memcpy(vis,vis1,sizeof(vis1));
			granum=granum1;
			ans=min(bfs(grass[i],grass[j]),ans);
		}
	}
if(ans!=999999)printf("Case %d: %d\n",cas,ans);
else printf("Case %d: -1\n",cas);
	}
 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值