收集纸片【状压bfs】

收集纸片 


题目描述

我们把房间按照笛卡尔坐标系进行建模之后,每个点就有了一个坐标。

假设现在房子里有些纸片需要被收集,收集完纸片你还要回归到原来的位置,你需要制定一个策略来使得自己行走的距离最短。

你只能沿着 x 轴或 y 轴方向移动,从位置 (i,j) 移动到相邻位置 (i+1,j),(i-1,j),(i,j+1) 或 (i,j-1) 距离增加 1。

输入描述:

在第一行中给出一个T,1≤T≤10, 代表测试数据的组数。

对于每组输入,在第一行中给出房间大小,第二行给出你的初始位置。

接下来给出一个正整数 n,1≤n≤10代表纸片的个数。

接下来 n 行,每行一个坐标代表纸片的位置。

保证房间小于 20×20,纸片一定位于房间内。

输出描述:

对于每组输入,在一行中输出答案。

格式参见样例。

示例1

输入

1
10 10
1 1
4
2 3
5 5
9 4
6 5

输出

The shortest path has length 24

思路:

  • 状压BFS. 将纸片标号[0, tot),然后二进制状态下表示。对应位为0,表示当前状态没有捡到对应纸片,对应为1,表示当前状态已经捡到了对应纸片.满状态当然就是每一位都为1,也就是(1 << tot) - 1啦~

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;

typedef long long ll;

inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -f; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}

//状压bfs

const int maxN = 25;

const int dir[4][2] = {
        1, 0,
        0, 1,
        -1, 0,
        0, -1
};

int n, m, tot;
int sx, sy;
int mp[maxN][maxN];
bool vis[maxN][maxN][1 << 11];

void init()
{
    memset(mp, -1, sizeof(mp));
    memset(vis, false, sizeof(vis));
}

bool InMap(int x, int y)
{
    return x >= 1 && x <= n && y >= 1 && y <= m;
}

struct node{
    int x, y, dis, sta;
};

int bfs()
{
    queue<node>q;
    node s = node{sx, sy, 0, 0};
    if(~mp[sx][sy]) s.sta |= mp[sx][sy];
    q.push(s);
    vis[sx][sy][s.sta] = true;
    while(!q.empty())
    {
        node tp = q.front(); q.pop();
        for(int i = 0; i < 4; ++ i )
        {
            int xx = tp.x + dir[i][0];
            int yy = tp.y + dir[i][1];
            node nex = node{xx, yy, tp.dis + 1, tp.sta};
            if(~mp[xx][yy])
                nex.sta |= (1 << mp[xx][yy]);
            if(!InMap(xx, yy) || vis[xx][yy][nex.sta]) continue;
            q.push(nex);
            vis[xx][yy][nex.sta] = true;
            if(nex.sta == (1 << tot) - 1)
                return nex.dis + abs(sx - xx) + abs(sy - yy);
        }
    }
}

int main()
{
    int TAT; TAT = read();
    while(TAT -- )
    {
        n = read(); m = read();
        sx = read(); sy = read();
        init();
        tot = read();
        for(int i = 1; i <= tot; ++ i)
        {
            int x, y; x = read(); y = read();
            mp[x][y] = i - 1;
        }
        printf("The shortest path has length %d\n", bfs());
    }
    return 0;
}
/*
1
5 5
1 1
4
2 3
3 4
4 5
5 3

1
2 2
1 1
1
2 2
 */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值