洛谷 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;
}

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

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

猜你喜欢

转载自www.cnblogs.com/zhouzhihao/p/10164263.html