Toyota Programming Contest 2023#4(AtCoder Beginner Contest 311)D-Grid Ice Floor

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 3N,M200
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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GaoGuohao2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值