Dragon slayer

在这里插入图片描述

  • 墙只有15个,因此可以二进制状态枚举拆哪些墙,用dfs如果能走到终点,就统计答案的最小值
  • 0.5处理:将所有坐标乘以二,并且0.5坐标还要+1;注意在坐标转移的时候也要*2才行;还有整个迷宫也要 *2;考虑原先0.5的时候墙的坐标是整数,现在人的坐标也是整数了,坐标转移的时候是判断不要 *2的走法有没有穿墙;数组大小也要乘二
  • 要将所有墙上的每个点标记是哪个墙;
  • 坐标转移判断:首先是范围;然后关于墙,是看方向以及是否穿墙;如果要走的点没有被走过,那么看要走的点是不是没有墙或者墙被拆了
  • 由于二进制表示第几个墙,因此,地图要初始化为-1
#include <iostream>
#include <cstring>
using namespace std;
const int N = 50;

int n, m, k;
int g[N][N];
int sx, sy, ex, ey;
bool st[N][N];
int ans;
int now;
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};

void dfs(int x, int y) {
    if (x == ex && y == ey) {
        int cc = 0, cct = now;
        while (cct) {
            if (cct & 1) cc ++ ;
            cct >>= 1;
        }
        ans = min(ans, cc);
        return ;
    }
    for (int d = 0; d < 4; ++ d) {
        int nx = x + 2 * dx[d], ny = y + 2 * dy[d];
        if (nx < 0 || nx > n || ny < 0 || ny > m) continue;
        int qq = -1;
        if (d <= 1 && g[x + dx[d]][y] != -1) {
            qq = g[x + dx[d]][y];
        }
        if (d > 1 && g[x][y + dy[d]] != -1) {
            qq = g[x][y + dy[d]];
        }
        if (!st[nx][ny]) {
            if (qq == -1 || (now >> qq & 1)) {
                st[nx][ny] = true;
                dfs(nx, ny);
            }
        }
    }
}

int main() {
    int _; cin >> _;
    while (_ -- ) {
        cin >> n >> m >> k;
        cin >> sx >> sy >> ex >> ey;
        sx *= 2; sy *= 2; ex *= 2; ey *= 2;
        sx ++ ; sy ++ ; ex ++ ; ey ++ ;
        n *= 2; m *= 2;
        memset(g, -1, sizeof g);
        for (int i = 0; i < k; ++ i) {
            int x1, y1, x2, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            x1 *= 2; y1 *= 2; x2 *= 2; y2 *= 2;
            if (x1 == x2) {
                if (y1 > y2) swap(y1, y2);
                for (int j = y1; j <= y2; ++ j) g[x1][j] = i;
            } else {
                if (x1 > x2) swap (x1, x2);
                for (int j = x1; j <= x2; ++ j) g[j][y1] = i;
            }
        }
        ans = 1e9;
        for (int i = 0; i < (1 << k); ++ i) {
            now = i;
            memset(st, 0, sizeof st);
            dfs(sx, sy);
        }
        cout << ans << endl;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值