[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)

posted @ 2018-05-26 22:51  NewErA  阅读(284)  评论(0编辑  收藏  举报