Knight's Trip 马在无线大棋盘上跳到指定点最小步数问题

题目描述

Problem D: Knight‘s Trip

In chess, each move of a knight consists of moving by two squares horizontally and one square vertically, or by one square horizontally and two squares vertically. A knight making
one move from location (0,0) of an infinite chess board would end up at one of the following eight locations: (1,2), (-1,2), (1,-2), (-1,-2), (2,1), (-2,1), (2,-1), (-2,-1).

Starting from location (0,0), what is the minimum number of moves required for a knight to get to some other arbitrary location (x,y)?

输入要求

Each line of input contains two integers x and y, each with absolute value at most one billion. The integers designate a location (x,y) on the infinite chess board. The final line contains the wordEND.

输出要求

For each location in the input, output a line containing one integer, the minimum number of moves required for a knight to move from (0,0) to (x,y).

假如输入

1 2
2 4
END

应当输出

1
2

这题不能用bfs,bfs代码如下,因为棋盘很大,会空间不足,但可以用bfs打印出棋盘来状况来分析,这题做了好久- -、、、、

#include<iostream>
#include<algorithm>
#include <vector>
#include<string.h>
#include<ctype.h>
#include<math.h>
using namespace std;
int map[1005][1005];
int res[1005][1005];
struct point
{
	int x,y;
};
struct point r[1005];
int dis[8][2]={{1,2},{-1,2},{1,-2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}};
int m,n;
void bfs()
{
	int tail=1, head=0,i,x1,y1;
	r[0].x=2;
	r[0].y=2;
	while(tail != head)
	{
		x1=r[head].x;
		y1=r[head].y;
		for(i=0; i<8; i++)
		{
			x1+=dis[i][0], y1+=dis[i][1];
			if(map[x1][y1]==0&&res[x1][y1]==-1)
			{
				r[tail].x=x1;
				r[tail].y=y1;
				res[x1][y1] = 1 + res[x1-dis[i][0]][y1-dis[i][1]];
				tail++;
			}
			x1-=dis[i][0], y1-=dis[i][1];
		}
		head++;
		if(res[m+2][n+2]!=-1)
			break;
	}
}
void fun();
int main()
{
    fun();
    return 0;
}
void fun()
{
	int i,j;
	while(cin>>m>>n)
	{
		memset(map,-1,sizeof(map));
		memset(res,-1,sizeof(res));
		m=abs(m);
		n=abs(n);
		if(m>n)
		{
			int temp=m;
			m=n;
			n=temp;
		}
		for(i=2;i<m+3;i++)
		{
			for(j=2;j<n+3;j++)
				map[i][j]=0;
		}
		res[2][2]=0;//棋盘0,0点
		res[3][3]=2;//棋盘1,1坐标要自己赋值,否则bfs算出来是4是错误的,因为我们把棋盘只考虑成第一象限的了
		bfs();
		for(i=2;i<m+3;i++)
		{
			for(j=2;j<n+3;j++)
				printf("%3d",res[i][j]);
			cout<<endl;
		}
		cout<<res[m+2][n+2]<<endl;
	}
}

可以用枚举来解决,如下

n=2*m这种情况直接就是(m+n)/3步。

如果n<2*m但是(m+n)%3==0的话,那么我们可以通过控制(1,2),(2,1)两种跳法的次数达到...总数必然是(m+n)/3,然后m,n的和对3取余是1的话,我们是不是必然可以在(m+n-1)/3步的时候跳到(m,n-1)这个点,但是不能一步跳到(m,n),回撤两步到(m-4,n-5)这个点,我们可以用三步跳到(m,n),那么就是原先的步数+1。余数为2,就是先跳到(m-1,n-1)这个地方,我们知道(0,0)到(1,1)只需要两步,那么(m-1,n-1)到(m,n)也就是原先步数+2.

然后考虑n>2*m,先把(0,1)的情况特殊处理一下。接着我们可以用m步跳到(m,n),那么原问题就转化为(0,0)到(0,n-2*m)。当n-2*m是4的倍数的话我们可以直接(1,2)(-1,2)这个跳可以在(n-2*m)/2步到达。余数为1,就是(0,0)到(0,1)的问题,但是这个需要三步不是最优的,我们后撤两步变为(0,0)到(0,5),我们可以三步达到,那么就是原先的步数加上1就是解。余数为2,我们可以分别跳一次(2,1)(-2,1)到达。余数为3,转化为(0,0)到(0,3)的问题我们可以(-1,2)(1,1)(0,3)三步到达。

#include<iostream>
#include<algorithm>
#include <vector>
#include<string.h>
#include<ctype.h>
#include<math.h>
using namespace std;
void fun();
int main()
{
    fun();
    return 0;
}
void fun()
{
	int m,n;
	while(cin>>m>>n)
	{
		m=abs(m);
		n=abs(n);
		if(m>n)
		{
			int temp=m;
			m=n;
			n=temp;
		}
		if(2*m>=n)
		{
			if(m==n&&m==1)
				cout<<2<<endl;
			else if(m==n&&m==2)
				cout<<4<<endl;
			else
				cout<<(m+n)/3+(m+n)%3<<endl;
		}
		else
		{
			int ans=m;
			int c=(n-2*m)%4;
			ans+=c;
			ans+=(n-2*m-c)/2;
			if(n==1&&m==0)
				ans=3;
			cout<<ans<<endl;
		}
	}
}

Knight's Trip 马在无线大棋盘上跳到指定点最小步数问题

时间: 2024-10-12 09:26:26

Knight's Trip 马在无线大棋盘上跳到指定点最小步数问题的相关文章

(数学)Knight&#39;s Trip -- hdu -- 3766

http://acm.hdu.edu.cn/showproblem.php?pid=3766 Knight's Trip Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 482    Accepted Submission(s): 106 Problem Description In chess, each move of a knigh

马哥教育大数据专家:深入解读大数据的就业前景

现在大数据越来越火热,很多人早早听说了大数据的名声,但对于大数据工程师这个职业的具体内容了解的还是不够.今天马哥教育(magedu.com)大数据专家为大家带来一份关于大数据工程师的详细分析,值得收藏~ 大数据工程师需要做什么呢? 大数据工程师就是一群"玩数据"的人,玩出数据的商业价值,让数据变成生产力.大数据和传统数据的最大区别在于,它是在线的.实时的,规模海量且形式不规整,无章法可循,因此"会玩"这些数据的人就很重要. 如果把大数据想象成一座不停累积的矿山,那么

(hdu step 4.2.3)Knight Moves(求从起点是否能够到达终点的最小步数)

题目: Knight Moves Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 453 Accepted Submission(s): 326   Problem Description A friend of you is doing research on the Traveling Knight Problem (TKP) where

十大基础实用算法之寻找最小(最大)的k个数-线性查找算法

例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4. 思路1:最容易想到的方法:先对这个序列从小到大排序,然后输出前面的最小的k个数即可.如果选择快速排序法来进行排序,则时间复杂度:O(n*logn) 注:针对不同问题我们应该给出不同的思路,如果在应用中这个问题的规模不大,或者求解前k个元素的频率很高,或者k是不固定的.那么我们花费较多的时间对问题排序,在以后是使用中可以线性时间找到问题的解,总体来说,那么思路一的解法是最优的. 思路2:在思路1的基础上更进一步

[BZOJ1193][HNOI2006]马步距离 大范围贪心小范围爆搜

1193: [HNOI2006]马步距离 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1988  Solved: 905[Submit][Status][Discuss] Description 在国际象棋和中国象棋中,马的移动规则相同,都是走"日"字,我们将这种移动方式称为马步移动.如图所示, 从标号为 0 的点出发,可以经过一步马步移动达到标号为 1 的点,经过两步马步移动达到标号为 2 的点.任给 平面上的两点 p 和 s ,它

【费马小定理】BZOJ3260 跳

Description 从(0,0)走到(n,m),没走过一个点(x,y)贡献为C(x,y),求最小贡献和. Solution 让我们guess一下 走的路线一定是先走长的一边再走短的一边,两条直线 然后就是求组合数了 这个可以递推,除的时候用费马小定理解决 Code get到了pow更短的写法 一开始m没取模溢出了几发 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<

HDU 1104 Remainder(BFS路径记录+数论)

Remainder Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4337    Accepted Submission(s): 1095 Problem Description Coco is a clever boy, who is good at mathematics. However, he is puzzled by a d

Knight&#39;s Trip---hdu3766(马走日求最小走的步数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3766 给你一个x ,y 求出从(0,0)位置到达需要的最小步数每次只能走日型: 下图为暴力bfs得到的答案:可以看一下: /** 首先,xy的大小排序和转化为都是正数步数不变应该懂吧. y=2*x这种情况直接就是(x+y)/3步. 如果y<2*x但是(x+y)%3==0的话,那么我们可以通过控制(1,2),(2,1) 两种跳法的次数达到...总数必然是(x+y)/3,然后xy的和对3取余是1的话,

北京大数据培训就选马哥教育:全新课程重磅出击

互联网的普及,使得人人都开始产生行为数据,在数据量越来越大的今天,大数据成为IT行业里技术含量最高.薪酬最高.成长空间最大的职位之一.企业在大数据方面的投入不断增加,对与人才的需求十分迫切. 据了解,未来3-5年,大数据行业人才缺口高达40万,部分企业甚至年薪20万招募0经验应届大学生从事大数据工作.马哥教育始终关注IT职业需求,为了帮助广大IT人实现年薪30万的大数据工程师梦想,重磅推出大数据课程. 深入了解行业发展,根据企业需求制定教学方案 马哥教育特聘10年开发经验的大数据专家.国内知名大