UVALIVE 5893 计算几何+搜索

题意:很复杂的题意,我描述不清楚。

题目链接:http://acm.bnu.edu.cn/bnuoj/contest_show.php?cid=3033#problem/33526

大致是,给定一个起点,一个终点,和一些墙,这些墙是不能越过的,然后一个人他每次走可以往四个方向走,可以加速,可以减速,也可以匀速。

也不一定是四个方向,因为他有一个VX,VY,所以每次走的方向其实都是不固定的,所以的四个方向就是他加速度的方向就是这四个。大家理解就好。

然后要从起点开始,走到终点,问最少需要多少步,而且走到终点的时候速度必须是0。

这道题的搜索部分其实很好想到,BFS开四维记录坐标和当前的VX,VY 。

因为速度有负的,所以我把起始速度开到16 。

然后搜索部分没什么问题了,对于计算几何部分的话,就是一个线段交的模版,没敲错基本上没问题。

CODE:.

#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <algorithm>
#define Max 2505
#define FI first
#define SE second
#define ll long long
#define PI acos(-1.0)
#define inf 0x3fffffff
#define LL(x) ( x << 1 )
#define bug puts("here")
#define PII pair<int,int>
#define RR(x) ( x << 1 | 1 )
#define mp(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i )

using namespace std;


inline int sgnInt(ll x){
    if(x < 0)return -1 ;
    return x > 0 ;
}
int n , m ;
int num ;
int sx , sy , ex , ey ;
struct WAll {
    int sx , sy , ex ,ey ;
} w[11] ;

#define N 64
int dis[N][N][32][32] ;
queue<pair<PII, PII> > qe ;
#define MP(a , b , c , d) mp(mp(a, b) , mp(c , d))
int mx[] = {1 , -1 , 0 ,0 , 0 } ;
int my[] = {0 , 0 , 0 ,1 , -1 } ;
int inmap(int x ,int y) {
    if(x >= 0 && x < n && y >= 0 && y < m)return 1 ;
    return 0 ;
}

struct Point{
    long long x, y;
    Point(const long long &x = 0, const long long &y = 0):x(x), y(y){}
    Point operator - (const Point  &a)const{ return Point(x - a.x, y - a.y);}
    bool operator <= (const Point &a)const{ return x <  a.x || (x == a.x && y <= a.y);}
    bool operator >= (const Point &a)const{ return x >  a.x || (x == a.x && y >= a.y) ;}
    friend long long det(const Point &a, const Point &b){ return a.x * b.y - a.y * b.x;}
    void in(){
        scanf("%lld %lld", &x, &y);
    }
};
struct Line{
    Point s, t;
    Line(const Point &s = Point(), const Point &t = Point()):s(s), t(t){}
    bool isSameSide(const Point &a, const Point &b)const{
        long long k1 = det(a - s, t - s), k2 =  det(b - s, t - s);
        return  sgnInt(k1) * sgnInt(k2) > 0;
    }
    friend bool lineInsectLine(Line &l1, Line &l2){
        if(l1.t <= l1.s)swap(l1.s, l1.t);
        if(l2.t <= l2.s)swap(l2.s, l2.t);
        if(det(l2.s - l1.s, l1.t - l1.s) == 0 && det(l2.t - l1.s, l1.t - l1.s) == 0
           &&det(l1.s - l2.s, l2.t - l2.s) == 0 && det(l1.t - l2.s, l2.t - l2.s) == 0){
            bool res1 = (l2.s <= l1.t && l2.s >= l1.s),
                 res2  =  (l2.t <= l1.t && l2.t >= l1.s),
                 res3 = (l1.s <= l2.t && l1.s >= l2.s),
                 res4 = (l1.t <= l2.t && l1.t >= l2.s);
                return res1 || res2 || res3 || res4;
        }
        return (!l1.isSameSide(l2.s, l2.t) && !l2.isSameSide(l1.s, l1.t));
    }
    void in(){
        s.in();
        t.in();
    }
};
int check(int x ,int y ,int xx ,int yy){
    Point p1(x ,y) ;
    Point p2(xx ,yy) ;
    Line l1(p1 , p2) ;
    for (int i = 0 ; i < num ; i ++ ){
        Point p3(w[i].sx , w[i].sy) ;
        Point p4(w[i].ex , w[i].ey) ;
        Line l2(p3 ,p4) ;
        if(lineInsectLine(l1 ,l2))return 1 ;
    }
    return 0 ;
}
int bfs() {
    while(!qe.empty())qe.pop() ;
    qe.push(MP(sx , sy , 16 , 16)) ;
    for (int i = 0 ; i < N ; i ++ ) {
        for (int j = 0 ; j < N ; j ++ ) {
            for (int k = 0 ; k < N / 2; k ++ )
                for (int x = 0 ; x < N / 2 ; x ++ )
                    dis[i][j][k][x] = inf ;
        }
    }
    dis[sx][sy][16][16] = 0 ;
    while(!qe.empty()) {
        pair<PII , PII > tp = qe.front() ;
        qe.pop() ;
        for (int i = 0 ; i < 5 ; i ++ ) {
            int vx = tp.SE.FI + mx[i] - 16 ;
            int vy = tp.SE.SE + my[i] - 16 ;
            int tx = tp.FI.FI + vx ;
            int ty = tp.FI.SE + vy ;
            if(inmap(tx ,ty) && vx > -16 && vy > -16 && vx < 16 && vy < 16 && !check(tp.FI.FI ,tp.FI.SE , tx ,ty)) {
                if(dis[tx][ty][vx + 16][vy + 16] > dis[tp.FI.FI][tp.FI.SE][vx - mx[i] + 16][vy - my[i] + 16] + 1 ) {
                    dis[tx][ty][vx + 16][vy + 16] = dis[tp.FI.FI][tp.FI.SE][vx - mx[i] + 16][vy - my[i] + 16] + 1 ;
                    qe.push(MP(tx , ty , vx + 16, vy + 16)) ;
                }
            }
        }
    }
    return dis[ex][ey][16][16] ;
}
int main() {
    while(cin >> m >> n ) {
        cin >> sy >> sx >> ey >> ex ;
        cin >> num ;
        for (int i = 0 ; i < num ; i ++ )cin >> w[i].sy >> w[i].sx >> w[i].ey >> w[i].ex ;
        int fk = bfs() ;
        cout << fk << endl;
    }
    return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值