• hdu 1010 解题报告 Tempter of the Bone


    hdu 1010 解题报告 ----Tempter of the Bone

    题意:输入一个n*m的迷宫,和一个T:可以在迷宫中生存的最大时间。S为起点,D为终点。并且,每个格子只能踩一次,且只能维持一秒,然后该块地板就会塌陷。所以你必须每秒走一步,且到D点时,所用时间为T。用深搜。

    本题要点:看是否能在所有可能的路中找到刚好满足条件(到达终点时门恰好打开)的路程,本题需要注意,单用深搜会超时,所以,有一个剪枝的地方非常重要!!!


    本来写的是java版,但不知为何提交不了就还原陈了C++版

    C++版:

     

    Problem : 1010 ( Tempter of the Bone )     Judge Status : Accepted
    RunId : 8246601    Language : C++    Author : luotianyu520
    Code Render Status : Rendered By HDOJ C++ Code Render Version 0.01 Beta
    #include<iostream>  
    using namespace std;  
    int sx,sy,ex,ey;  //起点和终点坐标
    int n,m;  //迷宫的行数列数
    char map[10][10];// 迷宫
    int flag;//判断成功
    int d[4][2]={0,1,1,0,0,-1,-1,0};  // 下、右、上、左
    void dfs(int x,int y,int t)  
    {   
        /** 1、排除并剪枝 */
        if(flag==1) return ;// 成功则返回
        // 剩余时间不足以走到终点 或者 当前点与终点横纵坐标差的和 与 剩余时间之差奇偶性不同。则直接否决返回
        if(t<abs(ex-x)+abs(ey-y)||(t-abs(ex-x)+abs(ey-y))%2) return ; 
        // 时间用完,则判断是否到终点并返回
        if(t==0) 
        {
            if(x==ex&&y==ey)  {flag=1; return ;}
            else { return ;  }
        }
        /** 2、递归四个方向 */
        for(int i=0;i<4;i++)                 
        {
            int nx=x+d[i][0],ny=y+d[i][1];//下一位置
            // 排除:1越界,2不是'.'或不是终点
            if (nx>0&&nx<=n&&ny>0&&ny<=m&&(map[nx][ny]=='.'||map[nx][ny]=='D'))
            {
                map[nx][ny]='X';//标记当前点走过         
                dfs( nx,ny,t-1) ;// 时间-1,递归下一点
                map[nx][ny]='.';//还原状态         
            }
    
        }  
        return ;  
    }  
    int main()  
    {  
    
    
        char str[10];    
        int t;  
        while (scanf("%d%d%d",&n,&m,&t)!=EOF)  
        {     
            if(n==0&&m==0&&t==0) return 0;  
            for (int i=1;i<=n;i++)  
            {  
                scanf("%s",str);  
                for (int j=1;j<=m;j++)  
                {  
                    map[i][j]=str[j-1];     
                    if(map[i][j]=='S')  sx=i,sy=j;  
                    else if(map[i][j]=='D') ex=i,ey=j;  
                }  
            }           
            flag=0;  
            dfs(sx,sy,t);  
            if(flag==0) printf("NO\n");  
            else printf("YES\n");   
        }  
        return 0;  
    }
    #include<iostream>  
    using namespace std;  
    int sx,sy,ex,ey;  //起点和终点坐标
    int n,m;  //迷宫的行数列数
    char map[10][10];// 迷宫
    int flag;//判断成功
    int d[4][2]={0,1,1,0,0,-1,-1,0};  // 下、右、上、左
    void dfs(int x,int y,int t)  
    {   
        /** 1、排除并剪枝 */
        if(flag==1) return ;// 成功则返回
        // 剩余时间不足以走到终点 或者 当前点与终点横纵坐标差的和 与 剩余时间之差奇偶性不同。则直接否决返回
        if(t<abs(ex-x)+abs(ey-y)||(t-abs(ex-x)+abs(ey-y))%2) return ; 
        // 时间用完,则判断是否到终点并返回
        if(t==0) 
        {
            if(x==ex&&y==ey)  {flag=1; return ;}
            else { return ;  }
        }
        /** 2、递归四个方向 */
        for(int i=0;i<4;i++)                 
        {
            int nx=x+d[i][0],ny=y+d[i][1];//下一位置
            // 排除:1越界,2不是'.'或不是终点
            if (nx>0&&nx<=n&&ny>0&&ny<=m&&(map[nx][ny]=='.'||map[nx][ny]=='D'))
            {
                map[nx][ny]='X';//标记当前点走过         
                dfs( nx,ny,t-1) ;// 时间-1,递归下一点
                map[nx][ny]='.';//还原状态         
            }
    
        }  
        return ;  
    }  
    int main()  
    {  
    
    
        char str[10];    
        int t;  
        while (scanf("%d%d%d",&n,&m,&t)!=EOF)  
        {     
            if(n==0&&m==0&&t==0) return 0;  
            for (int i=1;i<=n;i++)  
            {  
                scanf("%s",str);  
                for (int j=1;j<=m;j++)  
                {  
                    map[i][j]=str[j-1];     
                    if(map[i][j]=='S')  sx=i,sy=j;  
                    else if(map[i][j]=='D') ex=i,ey=j;  
                }  
            }           
            flag=0;  
            dfs(sx,sy,t);  
            if(flag==0) printf("NO\n");  
            else printf("YES\n");   
        }  
        return 0;  
    }
    

    Java版(答案没问题,可惜就是不知道哪不对,若有人找到不胜感激):

     

    package code.part3.problem;
    
    import java.util.Scanner;
    
    public class Main {
    	static Scanner scanner = new Scanner(System.in);
    	static int n, m, time;// 迷宫的行,列,时间
    	static char[][] map = new char[105][105];// 迷宫
    	static Point start = new Point(), end = new Point();// 起点、终点
    	static int[][] move = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };// 下、右、上、左
    	static boolean flag = false;
    
    	private static class Point {
    		int x;
    		int y;
    	}
    
    	public static void main(String args[]) {
    		while (scanner.hasNextInt()) {
    			n = scanner.nextInt();
    			m = scanner.nextInt();
    			time = scanner.nextInt();
    			if (n <= 1 || m >= 7 || time >= 50)
    				return;
    
    			init();
    			dfs(start, time);
    			
    			if (flag)	System.out.printf("YES\n");
    			else	System.out.printf("NO\n");
    		}
    		scanner.close();
    	}
    
    	public static void init() {
    		flag = false;
    		for (int i = 0; i < n; i++) {
    			map[i] = scanner.next().toCharArray();
    			for (int j = 0; j < m; j++) {
    				if (map[i][j] == 'S') {
    					start.x = i;
    					start.y = j;
    				} else if (map[i][j] == 'D') {
    					end.x = i;
    					end.y = j;
    				}
    			}
    		}
    	}
    
    	public static void dfs(Point fromP, int time) {
    		/** 1、排除并剪枝 */
    		// 成功则返回
    		if (flag)
    			return;
    		// 剩余时间不足以走到终点 或者 当前点与终点横纵坐标差的和 与 剩余时间之差奇偶性不同。则直接否决返回
    		if (time < Math.abs(end.x - fromP.x) + Math.abs(end.y - fromP.y)
    				|| (time - Math.abs(end.x - fromP.x) + Math
    						.abs(end.y + fromP.y)) % 2 == 1)
    			return;
    		// 时间用完,则判断是否到终点并返回
    		if (time == 0) {
    			if (fromP.x != end.x || fromP.y != end.y)
    				return;
    			flag = true;
    			return;
    		}
    
    		/** 2、递归四个方向 */
    		for (int i = 0; i < 4; i++) {
    			Point toP = new Point();
    			// 新位置
    			toP.x = fromP.x + move[i][0];
    			toP.y = fromP.y + move[i][1];
    			// 排除:1越界,2不是'.'或不是终点,直接下一个
    			if (toP.x < 0 || toP.y < 0 || toP.x >= n || toP.y >= m
    					|| (map[toP.x][toP.y] != '.' && map[toP.x][toP.y] != 'D'))
    				continue;
    			map[toP.x][toP.y] = 'X';// 标记当前点走过
    			dfs(toP, time - 1);// 时间-1,递归下一点
    			map[toP.x][toP.y] = '.';// 还原状态
    		}
    	}
    }
  • 相关阅读:
    vc 网络编程(socket)
    《精通Windows API-函数、接口、编程实例》——第4章文件系统
    WindowsAPI使用详解——GetVersion|GetVersionEx 获取操作系统版本和名称
    Windows编程 鼠标
    Windows 编程 键盘
    Windows编程 Windows程序的生与死(下)
    二叉查找树——A1043.Is it a Binary Search Tree(25)
    Springboot + ElasticSearch 构建博客检索系统
    树的遍历——A1053.Path of Equal Weight(30) 只可DFS不可BFS
    树的遍历——A1004.Counting Leaves(30) 给出一棵树,问每一层有多少叶子节点(可DFS也可BFS)
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3063521.html
Copyright © 2020-2023  润新知