题目描述
有天他来到一张方格地图上,整张地图可以看做一个二维坐标轴。牛牛此刻处于原点(0,0),他想要到点(x,y)去。牛牛有强迫症,他规定自己必须恰好k步走到点(x,y),中途可以经过任何点包括(x,y),但是第k步一定要到达(x,y)。
一步有八种走法,直线东(+1,0)南(0,-1)西(-1,0)北(0,+1),斜线东南(+1,-1)东北(+1,+1)西南(-1,-1)西北(-1,+1)。牛牛会在能k步到达目的地的基础下尽量走斜线,你能计算出牛牛到底走了多少条斜线吗?
输入描述
第一行一个整数T,代表数据组数。每组数据给出三个整数x,y,k。对于100%的数据,1<=T<=1000,
1<=x,y,k<=1000000000000000000。
输出描述
对于每组数据,单独一行输出一个整数。如果牛牛可以在第k步的时候到达(x,y),输出牛牛走的斜线数量。如果牛牛不能到达,输出-1。
解题思路
这道题感觉上和深搜类似,但实际差别很大,尤其是x,y,k的取值范围以及每一步的八个方向决定了搜索树相当大,因此深搜的方法不可靠。
题目要求首先要能够在k步到达, 其次要求要尽量走斜线达到。关于是否能够在k步内到达,由于在地图上从(0,0)点开始行走,沿着斜线方向效率最高,比如沿着y=x这条线上所有点都是可以直接全部沿着斜线到达,并且至少需要x步,如果指定步数小于x,那么不可达。由此拓展,发现在x+y=2n的直线上的所有点都是可以完全通过走直线达到,并且可以发现达到这些点的最少步数为max(x,y)。对于这些完全通过斜线到达的点,如果指定步数大于需要的步数,那么剩余部分是偶数则这一部分完全可以通过走斜线消耗掉,是奇数则要用两条直线代替一条斜线(这部分画图就可以清楚)。
对于那些不在上述线上的点,可以发现它的周围点都在这些线上,也就是说,走完斜线只需要再走一条直线就可以到达该点,达到该点的最小步数是周围点的最小步数加1。
上述分析在画图的情况下十分清晰。
代码实现
#include <iostream>
using namespace std;
unsigned long long max(unsigned long long x,unsigned long long y){
return x>y?x:y;
}
void getStep(unsigned long long x,unsigned long long y,unsigned long long k){
unsigned long long minstep,remins;
unsigned long long sum=x+y;
unsigned long long result;
if(sum%2==0){
minstep=max(x,y);
if(k<minstep)
cout<<-1<<endl;
else{
remins=k-minstep;
if(remins%2==0)
cout<<k<<endl;
else
cout<<k-2<<endl;
}
}else{
if(x>y)
minstep=x-1;
else
minstep=y-1;
if(k<minstep+1)
cout<<-1<<endl;
else
cout<<k-1<<endl;
}
return;
}
int main(){
unsigned long long t,x,y,k;
cin>>t;
while(t-->0){
cin>>x>>y>>k;
getStep(x,y,k);
}
return 0;
}