POJ 3985 Knight's Problem bfs + 剪枝

题意:在无限大的棋盘上给定起点和终点的坐标,然后给定n(0<=n<=10)个向量,问从起点走到终点最小的步数是多少。

题解:bfs是肯定的,但是裸的bfs会T,可以想象任意一个最短步数形成的路径任意交换两个选择的向量形成的路径是不一样的,那么一定能找到在路径中离

          l:(sx,sy)-> (tx,ty)直线最近的路径,所以只要找到这个路径即可,可以将所有背离起点终点和离 l 距离超过最大向量的点不入队,这样搜到

          的点的个数极限就是(5000 + 5000)* sqrt(2)* 10 * 2 * sqrt(2) = 400000,然后写个hash记录即可。

          开始用set< pair<int , int> >判重也会T,卡的好死唉。


Sure原创,转载请注明出处。

#include <iostream>
#include <cstdio>
#include <memory.h>
#include <queue>
#include <set>
#include <utility>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
#define sqr(x) ((x) * (x))
#define mp make_pair
typedef long long ll;
using namespace std;
const int maxn = 12;
const int maxm = 400000;
const int kr = 1;
const int prime = 999997;
struct ddd
{
    int x,y;
    int step;
};
struct node
{
    int x,y;
    int next;
}edge[maxm];
int head[prime],vec[maxn][2];
queue <ddd> Q;
int sx,sy,tx,ty,a,b,c,d,n,idx;

void init()
{
    memset(head,-1,sizeof(head));
    idx = 0;
    return;
}

int hash(int x,int y)
{
    return (((x << 15) ^ y) % prime + prime) % prime;
}

bool addedge(int key,int x,int y)
{
    for(int i=head[key];i != -1;i=edge[i].next)
    {
        if(edge[i].x == x && edge[i].y == y) return false;
    }
    edge[idx].x = x;
    edge[idx].y = y;
    edge[idx].next = head[key];
    head[key] = idx++;
    return true;
}

void read()
{
    d = 0;
    scanf("%d %d %d %d",&sx,&sy,&tx,&ty);
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d %d",&vec[i][0],&vec[i][1]);
        d = MAX(d , sqr(vec[i][0]) + sqr(vec[i][1]));
    }
    a = ty - sy;
    b = sx - tx;
    c = sy * tx - sx * ty;
    return;
}

bool IsValid(int x,int y)
{
    if(sqr(x - sx) + sqr(y - sy) <= sqr(kr) * d) return true;
    if(sqr(x - tx) + sqr(y - ty) <= sqr(kr) * d) return true;
    if((tx - sx) * (x - sx) + (ty - sy) * (y - sy) < 0) return false;
    if((sx - tx) * (x - tx) + (sy - ty) * (y - ty) < 0) return false;
    if(sqr(ll(a) * x + b * y + c) <= ll(d) * (sqr(a) + sqr(b))) return true;
    return false;
}

void bfs()
{
    while(!Q.empty()) Q.pop();
    ddd cur,tmp;
    tmp.x = sx;
    tmp.y = sy;
    tmp.step = 0;
    Q.push(tmp);
    addedge(hash(sx , sy) , sx , sy);
    while(!Q.empty())
    {
        cur = Q.front();
        Q.pop();
        if(cur.x == tx && cur.y == ty)
        {
            printf("%d\n",cur.step);
            return;
        }
        for(int i=0;i<n;i++)
        {
            int xx = cur.x + vec[i][0];
            int yy = cur.y + vec[i][1];
            if(IsValid(xx , yy) && addedge(hash(xx , yy) , xx , yy))
            {
                tmp.x = xx;
                tmp.y = yy;
                tmp.step = cur.step + 1;
                Q.push(tmp);
            }
        }
    }
    puts("IMPOSSIBLE");
    return;
}

int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        init();
        read();
        bfs();
    }
    return 0;
}

你可能感兴趣的:(c,struct,ini)