zoukankan      html  css  js  c++  java
  • UVA

    /*
    题目链接:
    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=380


    知识点:
    bfs
    dfs


    查阅资料汇总:
    http://blog.csdn.net/ns_code/article/details/19617187
    http://www.cnblogs.com/whywhy/p/4888632.html
    http://blog.csdn.net/dreamzuora/article/details/51137132
    http://blog.csdn.net/u011437229/article/details/53188837
    http://www.cnblogs.com/gczr/p/6476577.html
    https://zhidao.baidu.com/question/2011995849177182268.html

    */


    /*
    法一:
    参考了:
    http://www.cnblogs.com/xien0/archive/2013/08/08/Knigth-Moves.html
    
    法一没有用STL,它的思路要点在于:
    用数组来模拟队列
    
    这个思路我在之前做Java实验时也用过,链接见下:
    http://blog.csdn.net/mofushaohua_ln/article/details/78164383
    
    之所以自己重敲这个方法,还因为这个方法有点特别,一般我们是要会把棋盘设置为二维数组的,
    */
    #include <cstdio>
    #include <cstring>
    #define rep(i, n) for (int i = 0; i < (n); i++)
    int drc[8][2] = { { 1, 2 }, { 1, -2 }, { -1, 2 }, { -1, -2 }, { 2, -1 }, { 2, 1 }, { -2, 1 }, { -2, -1 } }; 
    //drc为骑士移动方向的坐标变化量, r::row, c:: column
    int que[100], vis[10][10], ans[10][10];
    
    void bfs(int r, int c)
    {
    	int tail = 1, head = 0; //队列的头和尾
    	que[head] = r * 8 + c;
    	vis[r][c] = 1; 
    	
    	while (tail > head)
    	{
    		int now = que[head++]; //取列表的首元素
    		r = now / 8, c = now % 8;
    		vis[r][c] = 1;
    		rep(i, 8)
    		{
    			int r1 = r + drc[i][0], c1 = c + drc[i][1];
    			if ( r1 >= 0 && r1 < 8 && c1 >= 0 && c1 < 8 && !vis[r1][c1] ) //选取可走的方向中,没有被访问的位置
    			{
    				que[tail++] = r1 * 8 + c1; //该位置入队
    				ans[r1][c1] = ans[r][c] + 1; //更新所走步数
    				vis[r1][c1] = 1; 
    			} 
    		} 
    	}
    }
    
    int main()
    {
    	int m, n;
    	char a, b;
    	
    	while ( scanf("%c%d %c%d", &a, &m, &b, &n) != EOF )
    	{
    		getchar(); //吃到末尾的回车,以免它作为下一组输入的第一个字符 a 被读入
    		memset( vis, 0, sizeof(vis) );
    		memset( ans, 0, sizeof(ans) );
    		
    		bfs(m - 1, a - 'a'); //这样处理,使得 a1 位置的坐标为 (0, 0)
    		printf( "To get from %c%d to %c%d takes %d knight moves.
    ", a, m, b, n, ans[n - 1][b - 'a'] ); 
    	}
    	return 0;
    }
    


    /*
    法二:
    参考了:
    http://blog.csdn.net/rowanhaoa/article/details/7803673
    
    该题是用dfs做的,注意理解递归
    */
    
    #include <cstdio>
    #include <iostream>
    #define rep(i, n) for ( int i = 0; i < (n); i++ )
    using namespace std;
    int a, b, x, y;
    int ans;
    char s1[100], s2[100];
    int drc[8][2] = { { 1, 2 }, { 1, -2 }, { -1, 2 }, { -1, -2 }, { 2, -1 }, { 2, 1 }, { -2, 1 }, { -2, -1 } }; 
    
    bool isin(int a, int x)
    {
    	return ( a >= 0 && a < 8 && x >= 0 && x < 8 );
    }
    
    void dfs(int a, int x, int sum)
    {
    	if (sum >= ans) return;
    	if ( a == b && x == y)
    	{
    		ans = min(ans, sum);
    		return;
    	}
    	
    	rep(i, 8)
    	{
    		int r = a + drc[i][0], c = x + drc[i][1];
    		if ( isin(r, c) ) dfs(r, c, sum + 1);
    	}
    }
    
    int main()
    {
    	while  (scanf("%s%s", s1, s2) != EOF )
    	{
    		ans = 6;
    		a = s1[0] - 'a', x = s1[1] - '1';
    		b = s2[0] - 'a', y = s2[1] - '1';
    		
    		dfs(a, x, 0);
    		printf( "To get from %s to %s takes %d knight moves.
    ", s1, s2, ans );
    	}
    	
    	return 0;
    }
    
    

    /*
    另外,本题也可用结构体,不过比前两种写法要繁琐一些...链接见下:
    http://blog.csdn.net/mobius_strip/article/details/13089747
    */


  • 相关阅读:
    底层因为接受到操作系统信号而停止的解决
    C语言判断文件是否存在
    Linux磁盘设备文件(sda,sdb,sdc…)变化问题
    linux mysql 数据目录文件夹移动及所遇到的问题
    Linux Mysql如何移动MySQL数据库目录位置
    Linux 磁盘挂载和mount共享
    提高VS2010/VS2012编译速度
    C++[类设计] ini配置文件读写类config
    WIN32读写INI文件方法
    MS509Team----------------Cknife
  • 原文地址:https://www.cnblogs.com/mofushaohua/p/7789352.html
Copyright © 2011-2022 走看看