论奇怪剪枝(第一弹)
题目描述
有一个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; }
已经有了卡常数大法,是不是可以有砍大数大法呢?
神奇的剪枝 第一弹 到此结束!