BNUOJ-4052-BT马

众所周知,国际象棋中的马的跳跃规则,假设将国际象棋棋盘看做一个十字坐标平面,当前马的坐标为(x,y),则马可跳跃到(x-2,y+1),(x-1,y+2),(x+1,y+2),(x+2,y+1),(x+2,y-1),(x+1,y-2),(x-1,y-2),(x-2,y-1)这8个位置。

现在已知有只BT马,它的跳跃方式就两种,假设当前坐标为(x,y),则这只BT马只可以跳跃到(x+n,y+n+1)或(x+n+1,y+n)这两个位置,其中n > 0。现在问题来了,设BT马的起始位置为(0,0),给出坐标(x,y),问BT马是否能通过有限次跳跃到达(x,y)这个位置。

Input
第一行两个正整数x,y(0 < x, y <= 10000),相隔一个空格。
第二行一个正整数n(0 < n <= 10000)。

Output
如果可以到达输出Yes,反之,No。

Sample Input
3 3
1
Sample Output
Yes
Hint
n = 1 说明该BT马可以从当前坐标(x,y) 跳到 (x+1,y+2) 或 (x+2,y+1) 这两个位置
需要两步从(0,0) 跳到 (3,3):
第一种跳法:(0,0) –> (1,2) –> (3,3)
第二种跳法:(0,0) –> (2,1) –> (3,3)

对于这道题,思路很简单,用bfs,这是首选方法,然而我这样子做了,可是遇见了各种各样的问题,原因是这个代码是别人给我的一个代码让我修改,而不是我自己写的,于是我想起来了一句话,改代码对程序员而言真的是天大的灾难!

一开始遇见了爆内存的问题,于是我又改了数组大小,为了开小些数组,着实费了一番功夫,因为需要做一些特殊的处理,尝试了几种处理手段发现都有漏洞,终于最后还是让我改好了,可是提交上去,又出现了超时,我又给他加上了几个判断,听说这种处理办法叫做剪枝,把没有可能对的结果给提前剪去,省得后续的无用判断,然而再提交,竟然变成了编译错误,顿时懵逼了,没办法,打个断点瞅瞅吧,调试了半天,发现原来是朋友的一个数组调用越界了,本来应该写成i < 2的却写成了i <= 2,再次更改,过了,我再一看自己的代码,我顿时抓狂,原来这道题的测试数据这么弱,我的数组最大的只开了一个10X10的二维数组,竟然过了,而我原来没有做特殊处理时,开的可是10000X10000的超大二维数组,栈內直接爆掉了,只好开在了堆內,然而依然是爆了内存,经过查看别人的提交记录,发现经过我的层层优化,我的代码具有相比较最快的效率,最小的资源消耗,唯一牺牲掉的是代码长度,毕竟优化代码的过程中,经常会出现这样的情况,代码效率越来越高,可是代码长度越来越长。

代码的复杂度对我们而言不管是高的、低的,对计算机而言却都是一样的,计算机只在乎代码的效率,也就是代码的运算次数,所以,为了让计算机更好的拷贝式的工作,我们还是有必要消耗更多自己的时间去优化代码。

#include<stdio.h>

int book[10][10] = {0};

struct step
{
    int x;//int y;//int stepNum;    //步数
};

struct step que[100];

int main()
{
    int x, y, n;

    int next[2][2]= {{0, 1}, {1, 0}};
    int first = 1, last = 1;
    int i, tx, ty, tStepNum;
    scanf("%d %d", &x, &y);
    scanf("%d", &n);
    if (n > x || n > y)
    {
        printf("No\n");
        return 0;
    }

    que[last].x = 0;
    que[last].y = 0;
    que[last].stepNum = 0;
    last++;

    book[0][0] = 1;

    while(first < last)
    {
        for(i = 0; i < 2; i++)
        {
            tx = que[first].x + next[i][0];
            ty = que[first].y + next[i][1];
            tStepNum = que[first].stepNum + 1;

            if(book[tx][ty] == 0 && tx + tStepNum * n < x && ty + tStepNum * n < y)
            {
                //把这个点标记为已经走过
                // 注意广搜每个点只入队一次,所以和深搜不一样,不需要把book数组还原
                book[tx][ty] = 1;
                //插入新的点到队列中
                que[last].x = tx;
                que[last].y = ty;
                que[last].stepNum = tStepNum;
                last++;
            }
            if(tx + tStepNum * n == x && ty + tStepNum * n == y)
            {
                printf("Yes\n");
                return 0;
            }
        }

        first++;
    }

    printf("No\n");
    return 0;
}

假如你写了一个垃圾的程序用了600秒,那么一个计算机运算用了1秒,一千台计算机就是运行了一千秒,如果可以在上百万台计算机上运行时,那么消耗的就是上百万秒;而如果你多花600秒甚至6000秒去优化一个代码,使计算机的运算只用0.1秒,那么想想,上百万台计算机会节省多少工作时间,相比较,你消耗的时间也就发挥到了更大的价值。

可怜的是,你只有写了很高效的代码,才有机会在上百万上千万的计算机上运行,毕竟垃圾程序是活不下去的,在当下这种时间就是金钱的社会。所以自己以后能做到哪一步,和自己对效率的苛刻程度是有关的。

这还只是考虑到时间问题,如果再考虑到内存问题,那么差距是不容估量的。

我一直无法理解很多人的想法,他们总是说有些算法之间的差距微乎其微,一般根本不用在意,他们说的在一定的范围内是对的,如果只有一台运行,那我绝对不去在乎差距不大的算法之间的差距,毕竟0.1秒和0.2秒对一个普通人而言,是没有多大区别的,感觉不出来,但是计算机层面的东西,哪里存在只运行几次的情况,计算机都是无数的算法堆积在一起反复使用,运算量之巨,足以巨大化任何一个微乎其微的差距,现在如此,未来更是如此。

个人观点,这就是国内计算机行业相对于美国一直处于劣势无法超越的根本原因,因为人家美国人甚至连一个运算符之间的差距都要考虑到,人家一开始就是把自己的程序当做是要在几百万的机子上运行的那种认真度来开发,纵使最后无法在几百万的机子上运行,那么人家的程序依然是一个优秀的程序,而国人则总是秉着中庸的思想,差不多就行了的想法,导致自己的程序也就是在小池子里冲冲凉,翻不了大浪。

作为一个程序猿,如果你不对自己的程序苛刻,那么就不要怪顾客对你苛刻!你只有做到比顾客更加苛刻,那么多数顾客才能买你的账。

如果马云的攻关团队对效率不苛刻,能一笔带过的细节都带过,那么我敢肯定双十一一定不会像现在这样称为疯狂的购物节,震撼世界!

你可能感兴趣的:(bfs,BT马)