zoukankan      html  css  js  c++  java
  • 洛谷 P1443马的遍历

    论奇怪剪枝(第一弹)

    原题链接

    题目描述

    有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步

    输入输出格式

    输入格式:

     一行四个数据,棋盘的大小和马的坐标

     输出格式:

     一个n*m的矩阵,代表马到达某个点最少要走几步(左对齐,宽5格,不能到达则输出-1)

    一道很经典的广搜题

    但我们今天不讲它的标程

    作为广搜菜鸟的我看到这道题自信地打出了DFS+记忆化的没毛病代码(其实是个蒟蒻的记忆化)

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,x,y,i,j;
    int dx[10]={2,-2,2,-2,1,-1,1,-1};
    int dy[10]={1,-1,-1,1,2,-2,-2,2};
    int a[450][450];
    void dfs(int x,int y,int tot)
    {
            if(tot>=a[x][y]&&a[x][y]!=-1) 
            {
                return;
            }
            else a[x][y]=tot;
        
        for(int i=0;i<8;i++)
        {
            if(x+dx[i]<=n&&x+dx[i]>=1&&y+dy[i]<=m&&y+dy[i]>=1)
            dfs(x+dx[i],y+dy[i],tot+1);
        }
        
    }
    int main()
    {
        cin>>n>>m>>x>>y;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            a[i][j]=-1;
        }
        dfs(x,y,0);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            printf("%-5d",a[i][j]);
            cout<<endl;
        }
        return 0;
    }

    用力地戳了提交键

    一定能过

    然而。。。

    80分!?

    两个点超时

    于是我用尽了毕生所学的卡常数大法

    也只卡到了90

    于是我观摩了一位同学AC的代码

    发现代码神似

    我看了半天,然后他告诉了我他代码的精髓

    概括为三个字:砍大数!!!

    然后我加了一句话(if(tot>=200) return),成功AC

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,x,y,i,j;
    int dx[10]={2,-2,2,-2,1,-1,1,-1};
    int dy[10]={1,-1,-1,1,2,-2,-2,2};
    int a[450][450];
    inline void dfs(int x,int y,int tot)
    {
            if((tot>=a[x][y]&&a[x][y]!=-1)||tot>=200) //核心所在
            {
                return;
            }
            else a[x][y]=tot;
        
        for(int i=0;i<8;i++)
        {
            if(x+dx[i]<=n&&x+dx[i]>=1&&y+dy[i]<=m&&y+dy[i]>=1)
            dfs(x+dx[i],y+dy[i],tot+1);
        }
        
    }
    int main()
    {
        cin>>n>>m>>x>>y;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            a[i][j]=-1;
        }
        dfs(x,y,0);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=m;j++)
            printf("%-5d",a[i][j]);
            cout<<endl;
        }
        return 0;
    }

    已经有了卡常数大法,是不是可以有砍大数大法呢?

    神奇的剪枝 第一弹 到此结束!

  • 相关阅读:
    c# winform treelistview的使用(treegridview)
    基于Windows服务的聊天程序
    .Net Core集成Office Web Apps(二)
    .Net Core集成Office Web Apps(一)
    .Net页面局部更新的思考
    C#下载歌词文件
    jquery导航栏
    Select2下拉框总结
    数位dp入门(内容一样,新版格式)
    我的emacs简易配置
  • 原文地址:https://www.cnblogs.com/zhouzhihao/p/10164263.html
Copyright © 2011-2022 走看看