zoukankan      html  css  js  c++  java
  • CCF CSP 201312-5 I’m stuck!

    试题编号: 201312-5
    试题名称: I’m stuck!
    时间限制: 1.0s
    内存限制: 256.0MB
    问题描述:   给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思:
      '#': 任何时候玩家都不能移动到此方格;
      '+': 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
      '-': 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非'#'方格移动一格;
      '|': 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非'#'方格移动一格;
      '.': 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为'#',则玩家不能再移动;
      'S': 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
      'T': 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格。
      此外,玩家不能移动出地图。
      请找出满足下面两个性质的方格个数:
      1. 玩家可以从初始位置移动到此方格;
      2. 玩家不可以从此方格移动到目标位置。
    输入格式: 输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
    接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个'S'和一个'T'。
    输出格式: 如果玩家在初始位置就已经不能到达终点了,就输出“I'm stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。
    样例输入: 5 5
    --+-+
    ..|#.
    ..|##
    S-+-T
    ####.
    样例输出: 2
    样例说明: 如果把满足性质的方格在地图上用'X'标记出来的话,地图如下所示:
    --+-+
    ..|#X
    ..|##
    S-+-T
    ####X

    思路:

    1.用二维数组存储这个地图,然后分别进行两次dfs;
    2.分别用两个二维数组存储各个坐标是否可以从起点走到bool mvTo[55][55]、各个坐标是否可以走到终点bool toEnd[55][55]
    3.第一次dfs:起点从题目给的起点开始,往后dfs,每遍历到一个坐标,更新mvTo数组;第二次dfs:起点从题目给的终点开始,往前dfs,每遍历到一个坐标,更新toEnd数组;
    4.注意第二次dfs的时候不是往下走,是倒着走,需要注意规则的变换;
    5.最后遍历所有坐标,输出从起点可达且不可达到终点的坐标数量;

    代码:

    #define IOS ios_base::sync_with_stdio(0); cin.tie(0);
    #include<iostream>
    using namespace std;
    int r,c,si,sj,ti,tj;
    char Map[55][55];
    bool mvTo[55][55],toEnd[55][55];
    bool isLegal(int i,int j){
    	if(i>=1&&i<=r&&j>=1&&j<=c&&Map[i][j]!='#'&&!mvTo[i][j]) return true;
    	else return false;
    }
    bool risLegal(int i,int j){
    	if(i>=1&&i<=r&&j>=1&&j<=c&&!toEnd[i][j]) return true;
    	else return false;
    }
    void dfs(int i,int j){
    	mvTo[i][j]=true;
    	char c=Map[i][j];
    	if(c=='+'||c=='|'||c=='S'||c=='T'||c=='.'){
    		if(c!='.'&&isLegal(i-1,j)) dfs(i-1,j);
    		if(isLegal(i+1,j)) dfs(i+1,j);
    	}
    	if(c=='+'||c=='-'||c=='S'||c=='T'){
    		if(isLegal(i,j-1)) dfs(i,j-1);
    		if(isLegal(i,j+1)) dfs(i,j+1);
    	}
    }
    void rdfs(int i,int j){
    	toEnd[i][j]=true;
    	char c=Map[i-1][j];
    	if(risLegal(i-1,j)&&(c=='+'||c=='|'||c=='S'||c=='T'||c=='.')) rdfs(i-1,j);
    	c=Map[i+1][j];
    	if(risLegal(i+1,j)&&(c=='+'||c=='|'||c=='S'||c=='T')) rdfs(i+1,j);
    	c=Map[i][j-1];
    	if(risLegal(i,j-1)&&(c=='+'||c=='-'||c=='S'||c=='T')) rdfs(i,j-1);
    	c=Map[i][j+1];
    	if(risLegal(i,j+1)&&(c=='+'||c=='-'||c=='S'||c=='T')) rdfs(i,j+1);
    }
    int main(){
    	IOS;
    	cin>>r>>c;
    	for(int i=1;i<=r;i++){
    		for(int j=1;j<=c;j++){
    			cin>>Map[i][j];
    			if(Map[i][j]=='S') {si=i;sj=j;}
    			if(Map[i][j]=='T') {ti=i;tj=j;}
    		}
    	}
    	dfs(si,sj);
    	rdfs(ti,tj);
    	if(!toEnd[si][sj]) cout<<"I'm stuck!";
    	else{
    		int cnt=0;
    		for(int i=1;i<=r;i++)
    			for(int j=1;j<=c;j++)
    				if(mvTo[i][j]&&!toEnd[i][j]) cnt++;
    		cout<<cnt;
    	}
    	return 0;
    }
    
  • 相关阅读:
    ASP.NET编程中非常有用的例子
    打包样式资源
    9.使用类的2个注意点
    面向对象案例
    super必须放到子类this之前
    PHP:根据二维数组中的某个字段进行排序
    Vuex的五个核心属性
    利用按钮控制listview的当前选择项,滚动条跟随动
    c#通过进程名字获取进程路径
    判断客户端是否安装realplayer
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308954.html
Copyright © 2011-2022 走看看