[BZOJ 1193] 马步距离
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1193
Solution:
能立刻看出贪心算法,但发现在小数据时明显不适用
于是我们采取大数据时贪心,到一定范围时爆搜的算法
(似乎有点像AlphaGo的策略?)
在数据大于10时,我们每次将长边-2,短边-1,如有小于0的情况取绝对值即可(相当于选用对称方案)
用BFS预处理出数据<=10时的情况即可
Code:
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> P; int X1,Y1,X2,Y2,dist[105][105]; int dx[]={-2,-2,-1,-1,1,1,2,2},dy[]={1,-1,2,-2,2,-2,1,-1}; queue<P> que; void init() { memset(dist,0x3f,sizeof(dist)); dist[1][1]=0;que.push(P(1,1)); while(!que.empty()) { P t=que.front();que.pop(); for(int i=0;i<8;i++) { int fx=t.first+dx[i],fy=t.second+dy[i]; if(fx<0 || fx>12 || fy<0 || fy>12) continue; if(dist[fx][fy]>dist[t.first][t.second]+1) dist[fx][fy]=dist[t.first][t.second]+1,que.push(P(fx,fy)); } } } int main() { init(); scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2); int a=abs(X1-X2),b=abs(Y1-Y2),res=0; while((a>=10) || (b>=10)) { if(a>b) swap(a,b); a-=1;b-=2;res++; a=abs(a);b=abs(b); } a++;b++; printf("%d",res+dist[a][b]); return 0; }
Review:
1、如仅有适用于大数据时的贪心算法时,
考虑大数据时贪心,到满足时间复杂度时开始爆搜(很不错的思想)
2、能向各个方向移动的问题
如将数组左上角作为起点,一定要将边界空间留出(有时最优解需要往回走)
ex:此处第0行/列都是合法的,而-1行则可由第3行代替,便可不必考虑
更稳妥的方式是将起点设在中间,如(50,50)