bzoj4394【Usaco2015 Dec】Bessie

148 篇文章 0 订阅
18 篇文章 0 订阅

4394: [Usaco2015 dec]Bessie

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 56   Solved: 21
[ Submit][ Status][ Discuss]

Description

After eating too much fruit in Farmer John's kitchen, Bessie the cow is getting some very strange dreams! In her most recent dream, she is trapped in a maze in the shape of an N×M grid of tiles (1≤N,M≤1,000). She starts on the top-left tile and wants to get to the bottom-right tile. When she is standing on a tile, she can potentially move to the adjacent tiles in any of the four cardinal directions.

But wait! Each tile has a color, and each color has a different property! Bessie's head hurts just thinking about it:

    If a tile is red, then it is impassable.
    If a tile is pink, then it can be walked on normally.
    If a tile is orange, then it can be walked on normally, but will make Bessie smell like oranges.
    If a tile is blue, then it contains piranhas that will only let Bessie pass if she smells like oranges.
    If a tile is purple, then Bessie will slide to the next tile in that direction (unless she is unable to cross it). If this tile is also a purple tile, then Bessie will continue to slide until she lands on a non-purple tile or hits an impassable tile. Sliding through a tile counts as a move. Purple tiles will also remove Bessie's smell. 

(If you're confused about purple tiles, the example will illustrate their use.)

Please help Bessie get from the top-left to the bottom-right in as few moves as possible.

奶牛Bessie被困在了N*M的网格图迷宫中,她位于左上角(1,1),出口在右下角(N,M)。Bessie只能上下左右行走。

每块地砖都有一个颜色:

如果是红色,那么不可通行。

如果是粉色,那么可以通行。

如果是橙色,那么可以通行,但是会给Bessie带上橘子的气味。

如果是蓝色,那么当且仅当Bessie带着橘子的气味时,才可以通行。

如果是紫色,那么Bessie会保持原有方向滑过去,如果之后仍然是紫色,那么会继续滑。当滑到不是紫色的地砖上或者不可通行的时候,才会停下来。并且这会消除Bessie身上的气味。每一步滑行和走路一样,都需要耗费一单位时间。

请输出Bessie逃到出口所需的最短时间。

Input

The first line has two integers N and M, representing the number of rows and columns of the maze.

The next NN lines have MM integers each, representing the maze:

    The integer '0' is a red tile
    The integer '1' is a pink tile
    The integer '2' is an orange tile
    The integer '3' is a blue tile
    The integer '4' is a purple tile 

The top-left and bottom-right integers will always be '1'.

Output

A single integer, representing the minimum number of moves Bessie must use to cross the maze, or -1 if it is impossible to do so.

Sample Input

4 4
1 0 2 1
1 1 4 1
1 0 4 0
1 3 1 1

Sample Output

10

HINT

In this example, Bessie walks one square down and two squares to the right (and then slides one more square to the right). She walks one square up, one square left, and one square down (sliding two more squares down) and finishes by walking one more square right. This is a total of 10 moves (DRRRULDDDR).

Source



BFS,建图比较麻烦(详见代码)


这是标程

#include <iostream>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

using namespace std;

int dr[] = {-1, 0, 1, 0};
int dc[] = {0, -1, 0, 1};

struct state {
  int r;
  int c;
  int ld;
  bool smell;

  state(int r, int c, int ld, bool smell) :
      r(r), c(c), ld(ld), smell(smell) {
  }

  int pack() {
    return (smell ? 1 : 0) + 2 * (ld + 1) + 10 * c + 10000 * r;
  }

  static state unpack(int x) {
    return state(x / 10000, (x / 10) % 1000,
                 (x / 2) % 5 - 1, x & 1);
  }
};

int getcell(const vector<vector<int > >& A, int r, int c) {
  if (r < 0 || r >= A.size() || c < 0 || c >= A[r].size()) {
    return 0;
  }
  return A[r][c];
}

int main() {
  ios_base::sync_with_stdio(false);

  int N, M;
  cin >> N >> M;
  vector<vector<int > > A(N, vector<int>(M));
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
      cin >> A[i][j];
    }
  }
  queue<int> q;
  vector<int> D(10000000, -1);

  int s = state(0, 0, -1, false).pack();
  q.push(s);
  D[s] = 0;

  while (!q.empty()) {
    state st = state::unpack(q.front());
    q.pop();
//    cout<<st.r+1<<' '<<st.c+1<<' '<<st.ld<<' '<<st.smell<<endl;

    if (st.r == N - 1 && st.c == M - 1) {
      cout << D[st.pack()] << '\n';
      return 0;
    }
    if (A[st.r][st.c] == 4 && st.ld != -1) {
      int col = getcell(A, st.r + dr[st.ld], st.c + dc[st.ld]);
      if (col != 0 && col != 3) {
        state nst = state(st.r + dr[st.ld], st.c + dc[st.ld], st.ld, col == 2);
        if (D[nst.pack()] != -1) {
          continue;
        }
        D[nst.pack()] = D[st.pack()] + 1;
        q.push(nst.pack());
        continue;
      }
    }
    for (int i = 0; i < 4; i++) {
      int col = getcell(A, st.r + dr[i], st.c + dc[i]);
      if (col == 0 || (col == 3 && !st.smell)) {
        continue;
      }
      state nst = state(st.r + dr[i], st.c + dc[i], i,
                        col == 2 ? true : col == 4 ? false : st.smell);
      if (D[nst.pack()] != -1) {
        continue;
      }
      D[nst.pack()] = D[st.pack()] + 1;
      q.push(nst.pack());
    }
  }
  cout << "-1\n";
  return 0;
}


这是我的程序,有两个点WA...不知道为什么

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define maxn 1100
#define maxm 20000100
using namespace std;
int n,m,a[maxn][maxn],d[maxm];
int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
struct node
{
	int x,y,dir,sme;
}now,nxt;
queue<node> q;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline int num(node tmp)
{
	return tmp.sme+2*(tmp.dir+1)+10*(tmp.x-1)+10000*(tmp.y-1);
}
int main()
{
	n=read();m=read();
	F(i,1,n) F(j,1,m) a[i][j]=read();
	memset(d,-1,sizeof(d));
	now=(node){1,1,-1,0};
	d[num(now)]=0;
	q.push(now);
	while (!q.empty())
	{
		now=q.front();q.pop();
		cout<<now.x<<' '<<now.y<<endl;
		if (now.x==n&&now.y==m)
		{
			printf("%d\n",d[num(now)]);
			return 0;
		}
		if (a[now.x][now.y]==4&&now.dir!=-1)
		{
			int tx=now.x+dx[now.dir],ty=now.y+dy[now.dir];
			if (tx<1||tx>n||ty<1||ty>m) continue;
			if (a[tx][ty]!=0&&a[tx][ty]!=3)
			{
				nxt=(node){tx,ty,now.dir,a[tx][ty]==2};
				if (d[num(nxt)]!=-1) continue;
				d[num(nxt)]=d[num(now)]+1;
				q.push(nxt);
				continue;
			}
		}
		F(i,0,3)
		{
			int tx=now.x+dx[i],ty=now.y+dy[i];
			if (tx<1||tx>n||ty<1||ty>m) continue;
			if (a[tx][ty]==0||(a[tx][ty]==3&&!now.sme)) continue;
			int ts=a[tx][ty]==2?1:(a[tx][ty]==4?0:now.sme);
			nxt=(node){tx,ty,i,ts};
			if (d[num(nxt)]!=-1) continue;
			d[num(nxt)]=d[num(now)]+1;
			q.push(nxt);
		}
	}
	printf("-1\n");
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值