CodeForces - 1036B Diagonal Walking v.2(思维)

题目链接:点击查看

题目大意:给出m个询问,每个询问给出x y k,每次可以向当前点周围的八个方向移动,每个点可以经过任意次数,问从(0,0)点走到(x,y)点,使用的步数恰好为k时,走过的斜边的最大数目

题目分析:找规律的题,首先选出m和n中较大的那条边(这里我们假设m>=n),我们完全可以每次都斜着走,走m次后,一定能到(m,m)点,由于从(0,0)的距离到(m,m)的距离肯定大于等于到(n,m)的距离,所以我们可以反过来想,如果k小于m的话,那么最远也只能到达(k,k)点,所以无法达到(n,m)点,这个是一种判断,另一种是,如果m和n做差,结果是偶数的话,一定可以全部通过走斜边的方式经过(n,m)点,注意这里是经过而不是到达,具体的下面再说。我们接着分析,那如果是奇数的话,肯定需要用一次步数来横着走一次或竖着走一次才行,所以如果m和n做差的结果是奇数的话,我们令k-1。如果是偶数的话,我们还需要讨论k和m的关系,如果k和m的差值是偶数的话,那每当走到(n,m)点后,可以找一个邻近的斜边进行反复的来回走动,因为是偶数,所以最后走完k次后肯定会回到(n,m)点,所以答案就是k,但如果k和m的差值是奇数,那就说明先走到(n,m)点后来回反复走动,走完k次后,会回不到(n,m)点,那么我们就需要横着或竖着多走两次才行,这样就可以和最后的那一次斜着走抵消了,如果满足这个条件令k-2即可,分类讨论一下每种情况,最后输出k即可

上代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
   
const int N=25;
  
int main()
{
    int w;
    cin>>w;
    while(w--)
    {
    	LL n,m,k;
    	scanf("%lld%lld%lld",&n,&m,&k);
    	if(mk)
    	{
    		printf("-1\n");
    		continue;
		}
    	if((m-n)&1)//两边相差为奇数时,需要多走一个横着或竖着 
    		k--;
    	else if((k-m)&1)//两边相差为偶数时,如果剩余步数为奇数,需要多走两个横着或竖着
			k-=2;
		printf("%lld\n",k);//两边相差为偶数,且剩余步数为偶数时,k次全部用来斜着走即可
	}
      
      
      
      
      
      
      
      
      
      
    return 0;
}

 

你可能感兴趣的:(思维)