Toyota Programming Contest 2023#4(AtCoder Beginner Contest 311)D-Grid Ice Floor
Time Limit: 2 sec / Memory Limit: 1024 MB
Score : 400 points
Problem Statement
There is an N × M N×M N×M grid and a player standing on it.
Let (i,j) denote the square at the i-th row from the top and j-th column from the left of this grid.
Each square of this grid is ice or rock, which is represented by N strings S 1 , S 2 , … , S N S_1,S_2 ,…,S_N S1,S2,…,SN of length M M M as follows:
if the j j j-th character of S i S_i Siis ., square ( i , j ) (i,j) (i,j) is ice;
if the j j j-th character of S i S_i Siis #, square ( i , j ) (i,j) (i,j) is rock.
The outer periphery of this grid (all squares in the 1 1 1-st row, N N N-th row, 1 1 1-st column, M M M-th column) is rock.
Initially, the player rests on the square ( 2 , 2 ) (2,2) (2,2), which is ice.
The player can make the following move zero or more times.
First, specify the direction of movement: up, down, left, or right.
Then, keep moving in that direction until the player bumps against a rock. Formally, keep doing the following:
if the next square in the direction of movement is ice, go to that square and keep moving;
if the next square in the direction of movement is rock, stay in the current square and stop moving.
Find the number of ice squares the player can touch (pass or rest on).
Constraints
3 ≤ N , M ≤ 200 3≤N,M≤200 3≤N,M≤200
S i S_i Siis a string of length M M M consisting of # and …
Square ( i , j ) (i,j) (i,j) is rock if i = 1 , i = N , j = 1 , i=1, i=N, j=1, i=1,i=N,j=1, or j = M . j=M. j=M.
Square ( 2 , 2 ) (2,2) (2,2) is ice.
Input
The input is given from Standard Input in the following format:
N N N M M M
S 1 S_1 S1
S 2 S_2 S2
⋮
S N S_N SN
Output
Print the answer as an integer.
Sample Input 1
6 6
######
#....#
#.#..#
#..#.#
#....#
######
Sample Output 1
12
For instance, the player can rest on (5,5) by moving as follows:
(2,2)→(5,2)→(5,5).
The player can pass (2,4) by moving as follows:
(2,2)→(2,5), passing (2,4) in the process.
The player cannot pass or rest on (3,4).
Sample Input 2
21 25
#########################
#..............###...####
#..............#..#...###
#........###...#...#...##
#........#..#..#........#
#...##...#..#..#...#....#
#..#..#..###...#..#.....#
#..#..#..#..#..###......#
#..####..#..#...........#
#..#..#..###............#
#..#..#.................#
#........##.............#
#.......#..#............#
#..........#....#.......#
#........###...##....#..#
#..........#..#.#...##..#
#.......#..#....#..#.#..#
##.......##.....#....#..#
###.............#....#..#
####.................#..#
#########################
Sample Output 2
215
题目给定一个矩阵,'#‘表示岩石(障碍),’.'表示冰块(通路)。每次撞上岩石或者出发时可以选择一个方向行走直到再次撞上岩石,以此类推。试问有多少块冰块可以到达或经过?
很明显是搜索。
因为并不是最优路径问题,所以每一次的状态不应当重复。但是如何设计剪枝(记忆化)呢?
直接记录点肯定是不行的,因为在这个点上可能有四种不同的前进方向,所以数组也应该分别记录每个方向,当然我选择的是下面那种方法。
可以记录每一次转向时的状态(撞上岩石或出发时),也分为四个方向,如果之前有在撞上后选择相同方向的记录则return,也许你们会问这里为什么还要分四个方向,每一次搜索不都尝试了四个方向了吗?
如图。
在第一次到达后,vh[2][2]已经被标记,则后面来的会被误剪掉。
在代码中,1代表向上,2代表向下,3代表向左,4代表向右。
最后对于每个冰块,统计是否到达过。
我将撞墙后的剪枝数组与冰块是否到达的数组合并为一个,冰块是否到达默认存在了vh[i][j][1]。
#include <bits/stdc++.h>
#define int long long
using namespace std;
char a[210][210];
int n,m,vh[210][210][5],ans;//1x-- 2x++ 3y-- 4y++
void dfs(int x,int y){
int xx,yy;
xx=x,yy=y;
while(a[++xx][yy]=='.')vh[xx][yy][1]=1;
if(!vh[xx][yy][2]){
vh[xx][yy][2]=1;
dfs(xx-1,yy);
}
xx=x,yy=y;
while(a[--xx][yy]=='.')vh[xx][yy][1]=1;
if(!vh[xx][yy][1]){
vh[xx][yy][1]=1;
dfs(xx+1,yy);
}
xx=x,yy=y;
while(a[xx][++yy]=='.')vh[xx][yy][1]=1;
if(!vh[xx][yy][4]){
vh[xx][yy][4]=1;
dfs(xx,yy-1);
}
xx=x,yy=y;
while(a[xx][--yy]=='.')vh[xx][yy][1]=1;
if(!vh[xx][yy][3]){
vh[xx][yy][3]=1;
dfs(xx,yy+1);
}
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
cin>>a[i][j];
vh[2][2][1]=1;
dfs(2,2);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(a[i][j]=='.')ans+=vh[i][j][1];
cout<<ans<<endl;
return 0;
}