Aoj 0558 Cheese【bfs分段处理】

24 篇文章 0 订阅

网址:

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0558

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=108221#problem/E


题意:

在H * W的地图上有N个奶酪工厂,每个工厂分别生产硬度为1-N的奶酪。有一只老鼠准备从出发点吃遍每一个工厂的奶酪。老鼠有一个体力值,初始时为1,每吃一个工厂的奶酪体力值增加1(每个工厂只能吃一次),且老鼠只能吃硬度不大于当前体力值的奶酪。 

      老鼠从当前格到上下左右相邻的无障碍物的格需要时间1单位,有障碍物的格不能走。走到工厂上时即可吃到该工厂的奶酪,吃奶酪时间不计。问吃遍所有奶酪最少用时。 

输入:第一行三个整数H(1 <= H <= 1000)、W(1 <= W <=1000)、N(1 <= N <= 9),之后H行W列为地图, “.“为空地, ”X“为障碍物,”S“为老鼠洞, 1-N代表硬度为1-N的奶酪的工厂。输出最少用时。 

题意翻译参考自 http://bbs.byr.cn/#!article/ACM_ICPC/73337?au=Milrivel


因为给出的数字是连续的,初始的值是1,只能吃比自己体力小的奶酪,到达奶酪时可以选择吃或者不吃,所以每个位置可能经过多次,不能简单的标记,这样考虑:

因为题目限制,那么必定吃的数字的顺序是1 2 3 ...依次递增,那么就把这个总的任务分解成从 0(开始)到1,从1到2...分别求最短路径的情况,单独处理每一段,最后累加所有的最短时间,肯定是最优解了。


测试数据:

4 5 2
.X..1
....X
.XX.S
.2.X.
3 3 1
S..
...
..1
10 10 9
.X...X.S.X
6..5X..X1X
...XXXX..X
X..9X...X.
8.X2X..X3X
...XX.X4..
XX....7X..
X..X..XX..
X...X.XX..
..X.......


Ac代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=1005;
int n,m,k,dx[]={-1,1,0,0},dy[]={0,0,1,-1},vis[maxn][maxn];
char map[maxn][maxn];
struct maze
{
	int x,y,time;
};
maze bfs(int bx,int by,char ch)
{
	memset(vis,0,sizeof(vis));
	queue<maze> q;
	maze st={bx,by,0};
	q.push(st);vis[bx][by]=1;
	while(!q.empty())
	{
		st=q.front();q.pop();
		if(map[st.x][st.y]==ch)
		{
			return st;
		}
		for(int i=0;i<4;++i)
		{
			int tx=st.x+dx[i],ty=st.y+dy[i];
			if(tx<0||tx>=n||ty<0||ty>=m||map[tx][ty]=='X')//越界和墙 
			{
				continue;
			}
			maze tp={tx,ty,st.time+1};
			if(!vis[tx][ty])
			{
				vis[tx][ty]=1;
				q.push(tp);
			}
		}
	}
}
int main()
{
	//freopen("shuju.txt","r",stdin);
	while(~scanf("%d%d%d",&n,&m,&k))
	{
		int bx,by;
		for(int i=0;i<n;++i)
		{
			scanf("%s",map[i]);
			for(int j=0;j<m;++j)
			{
				if(map[i][j]=='S')
				{
					bx=i;by=j;
					map[i][j]='0'; //第0个起点 
				}
			}
		}
		int ans=0;
		for(int i=0;i<k;++i)
		{
			maze tp=bfs(bx,by,map[bx][by]+1);
			ans+=tp.time;
			bx=tp.x;by=tp.y;
		}
		printf("%d\n",ans);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值