洛谷 P1443馬的遍歷
阿新 • • 發佈:2018-12-23
論奇怪剪枝(第一彈)
題目描述
有一個n*m的棋盤(1<n,m<=400),在某個點上有一個馬,要求你計算出馬到達棋盤上任意一個點最少要走幾步
輸入輸出格式
輸入格式:
一行四個資料,棋盤的大小和馬的座標
輸出格式:
一個n*m的矩陣,代表馬到達某個點最少要走幾步(左對齊,寬5格,不能到達則輸出-1)
一道很經典的廣搜題
但我們今天不講它的標程
作為廣搜菜鳥的我看到這道題自信地打出了DFS+記憶化的沒毛病程式碼(其實是個蒟蒻的記憶化)
#include<bits/stdc++.h> usingnamespace 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; }
已經有了卡常數大法,是不是可以有砍大數大法呢?
神奇的剪枝 第一彈 到此結束!