题目:
在小美和小团生活的城市中,有n行m列共计n*m个十字路口,第i行j列的十字路口有两个属性aij,bij。当行人处在i行j列的路口,对于任意非负整数k: 当时间处在[k x aij+k x bij), (k+1) x aij+k x bij)时,行人可以选择走到i±1行j列的路口。 当时间处在[(k+1) x aij+k x bij), (k+1) x aij+(k+1) x bij)时,行人可以选择走到i行j±1列的路口。 每次移动花费的时间为1,且要保证将要去的十字路口存在,即属于n*m个路口当中。可以选择原地静止不动。 在第0时刻,小美处在xs行ys列的十字路口处,要去xt行yt列的十字路口找小团。小团原地不动等小美,请问小美所花费的时间最少是多少?
输入描述:
第一行六个正整数n,m,xs,ys,xt,yt,含义如上文所示。以样例第一行【5、5、2、4、4、3】 共计6个数字为例,前两位数字代表有5*5的二维数组,三、四位数字代表小美处在2行4列的十字路口处,五、六位数字代表要去4行3列的十字路口找小团。 接下来n行每行m个正整数,在样例中为第一个5*5的二维数组,第i行第j个数代表i行j列十字路口的属性aij。 接下来n行每行m个正整数,在样例中为第二个5*5的二维数组,第i行第j个数代表i行j列十字路口的属性bij。 对于100%的数据,1≤n,m,xs,ys,xt,yt,aij,bij≤100。
输出描述:
输出1行1个整数代表答案。
示例1
输入
5 5 2 4 4 3 2 1 1 3 1 1 4 2 3 1 4 4 4 2 1 3 1 1 2 4 5 1 5 5 1 5 3 4 1 3 1 1 2 2 2 2 1 4 4 5 1 1 5 3 3 3 2 1 3 3
输出
3
思路:
这道题一开始我使用DFS做的,但是只通过了百分之40的用例。 官方用BFS给我上了一课。 首先官方设了一个Node用来存x和y。 设置了一个directions数组用来存0,-1,1。即移动的三种状态。 以及一个标记数组mark。 cost作为当前已经花费的时间,每一次bfs的循环处理当前cost可能能走的几个位置。 即len=q.size()。 当前cost是x加还是y加由题目判断,即rest=cost%(axy+bxy),比如axy为2,bxy为5。 那么当rest<2即x加,不然y加。如果当前directions为0,那么也是一种情况。 如果加完以后的x和y是没有访问过的,即!mark ,那么入队作为下一秒的情况。 那么当某一次now.x==xt&&now.y==yt时,cost就可以返回了。 这道题的精髓就是用节点记录了某个点的位置,再通过directions数组来处理它,把每秒可能去的位置入队。
代码:
#include<bits/stdc++.h> using namespace std; int n, m, xs, ys, xt, yt; int a[101][101]; int b[101][101]; vector<int> directions = { 0,-1,1 }; bool mark[101][101]; struct node { int x, y; node() {} node(int a, int b) :x(a), y(b) {} }; int bfs() { queue<node> q; q.push(node(xs, ys)); int cost = 0; while (q.size() != 0) { int len = q.size(); for (int i = 0; i < len; ++i) { node now = q.front(); if (now.x == xt && now.y == yt)return cost; q.pop(); mark[now.x][now.y] = true; for (int j = 0; j < directions.size(); ++j) { int x = now.x; int y = now.y; if (x<1 || x>n || y<1 || y>m)continue; int rest = cost % (a[x][y] + b[x][y]); if (rest < a[x][y]) { x += directions[j]; } else { y += directions[j]; } if (j == 0 || !mark[x][y]) { q.push(node(x, y)); mark[x][y] = true; } } } cost++; } return cost; } int main() { memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); memset(mark, 0, sizeof(mark)); scanf("%d%d%d%d%d%d", &n, &m, &xs, &ys, &xt, &yt); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { scanf("%d", &a[i][j]); } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { scanf("%d", &b[i][j]); } } cout << bfs() << endl; return 0; } }