1. 程式人生 > >洛谷 P1443馬的遍歷

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

已經有了卡常數大法,是不是可以有砍大數大法呢?

神奇的剪枝 第一彈 到此結束!