标签:运动 namespace 注意 input first cpp 空格 point 表示
题目:
一场冰面比赛在一个矩形区域进行,区域上设置有障碍(1表示),空白区域(0表示),起点(2表示),终点(3表示)。起始在起点有一个石头,每次将它向上左下右四个方向之一抛出(当某一方向上临近有障碍时不能向这一方向抛出),石块将沿这一方向运动,直到:
一局游戏一共可以抛掷石头10次,如果10次后石头还没有到达终点,那么游戏失败。需要到达终点的最少抛掷次数。
样例输入:
2 1
3 2
6 6
1 0 0 2 1 0
1 1 0 0 0 0
0 0 0 0 0 3
0 0 0 0 0 0
1 0 0 0 0 1
0 1 1 1 1 1
6 1
1 1 2 1 1 3
6 1
1 0 2 1 1 3
12 1
2 0 1 1 1 1 1 1 1 1 1 3
13 1
2 0 1 1 1 1 1 1 1 1 1 1 3
0 0
样例输出:
1
4
-1
4
10
-1
思路:
_throw()
函数模拟每次石头向某一方向运动,返回三种结果:出界、到达终点、遇到障碍。代码:
#include <iostream>
#include <utility>
using namespace std;
typedef pair<int, int> PII;
const int N = 22;
const int dr[] = {0, 1, -1, 0};
const int dc[] = {1, 0, 0, -1};
int m, n;
int end_r, end_c; //终点的坐标
int g[N][N];
int cnt, steps;
int _throw(int start_r, int start_c, int dir, PII &end_point){
int raw = start_r, col = start_c;
while(1){
raw += dr[dir];
col += dc[dir];
// printf("cur_r: %d cur_c: %d\n", raw, col);
if(raw < 0 || raw >= m || col < 0 || col >= n){ // outside
end_point.first = start_r;
end_point.second = start_c;
return 0;
}
if(raw == end_r && col == end_c){ //arrive the end point
return 1;
}
if(g[raw][col] == 1){ //arrive a block
end_point.first = raw - dr[dir];
end_point.second = col - dc[dir];
return 2;
}
}
}
void dfs(int start_x, int start_y){
if(cnt > 10) return;
int condition;
for(int dir = 0; dir < 4; ++dir){
PII end_point;
end_point.first = start_x; end_point.second = start_y;
int tmpr = start_x + dr[dir];
int tmpc = start_y + dc[dir]; //用于判断“起点”四周是否有障碍阻挡抛出
if(tmpr>=0 && tmpr<m && tmpc>=0 && tmpc < n && g[tmpr][tmpc] != 1){ //当四周没有blocks时可以throw
condition = _throw(start_x, start_y, dir, end_point);
if(condition == 0) continue;
if(condition == 1){ //到达终点
if(cnt+1 < steps) {steps = cnt+1;} //更新最少到达的结果到steps中
continue;
}
if(condition == 2) {
int old_cnt = cnt; //保留当前状态的步数
cnt++;
g[end_point.first+dr[dir]][end_point.second+dc[dir]] = 0; //清除障碍
dfs(end_point.first, end_point.second); //进入下一状态
g[end_point.first+dr[dir]][end_point.second+dc[dir]] = 1; //恢复现场
cnt = old_cnt;
}
}
}
}
int main(){
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int start_r, start_c;
while(scanf("%d%d", &n, &m) && m != 0){
for(int i = 0; i < m; ++i){
for(int j = 0; j < n; ++j){
scanf("%d", &g[i][j]);
if(g[i][j] == 2){ start_r = i; start_c = j;}
if(g[i][j] == 3) { end_r = i; end_c = j;}
}
}
cnt = 0, steps = 100000;
dfs(start_r, start_c);
if(steps>10) printf("-1\n");
else printf("%d\n", steps);
}
}
标签:运动 namespace 注意 input first cpp 空格 point 表示
原文地址:https://www.cnblogs.com/patrolli/p/12188880.html