首页 > 其他分享 >poj 1324(BFS+状态压缩)

poj 1324(BFS+状态压缩)

时间:2023-05-29 19:33:50浏览次数:36  
标签:pre && 1324 int BFS poj dx dy dir


解题思路:这道题一开始的想法就是状态压缩,即考虑如何判重,由于蛇并非是直线的,所以想到了以每一个点的上下左右共四个

值来表示相对位置。最开始想如何用四进制来表示它,无语。。。。。还是题目做少了,直接用两位来表示一个点即可(两位的二

进制数可以表示0-3)。剩下的关键就是判断蛇头会不会与蛇尾发生碰撞,详细的就看代码吧。。

整体的思路还是比较简单,但是代码很复杂,一般这种复杂点的搜索题代码都挺长的,所以很容易出错,不过可以用A*算法,而且

确实比朴素的算法要快,暂时还没想清楚怎么做。。。




#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;

const int MAX_S = (1 << 14) + 100;
const int MAX_N = 20 + 2;
const int INF = (1 << 29);
struct State
{
    int x, y, dis, s;
    State(int x = 0, int y = 0, int dis = 0, int s = 0) : x(x), y(y), dis(dis), s(s) {};
};
struct Point
{
    int x, y;
};
int N, M, res, L;
int vis[MAX_N][MAX_N][MAX_S];
int fx[4] = {-1, 0, 1, 0};
int fy[4] = {0, 1, 0, -1};
bool _map[MAX_N][MAX_N];
Point pos[MAX_N * MAX_N];
queue <State> Q;

int get_start()
{
    int dir, dx, dy, s = 0;
    for(int i = L - 1; i > 0; i--)
    {
        dx = pos[i].x - pos[i - 1].x, dy = pos[i].y - pos[i - 1].y;
        if(dx == 0 && dy == 1)
            dir = 1;
        else if(dx == 0 && dy == -1)
            dir = 3;
        else if(dx == -1 && dy == 0)
            dir = 0;
        else if(dx == 1 && dy == 0)
            dir = 2;
        s = s << 2;
        s = s | dir;
    }
    return s;
}
int get_next_state(int i, int s)
{
    int dir;
    int k = (1 << ((L - 1) << 1)) - 1;
    int dx = 0, dy = 0;
    dx = dx - fx[i], dy = dy - fy[i];
    if(dx == 0 && dy == 1)
        dir = 1;
    else if(dx == 0 && dy == -1)
        dir = 3;
    else if(dx == -1 && dy == 0)
        dir = 0;
    else if(dx == 1 && dy == 0)
        dir = 2;
    s = s << 2;
    s = s | dir;
    s = s & k; // 去除高位部分
    return s;
}

bool judge_code(int x, int y, int pre_x, int pre_y, int s)
{
    int dir;
    for(int i = 0; i < L - 1; i++)
    {
        dir = 3;
        dir = dir & s;
        s = s >> 2;
        if(x == pre_x + fx[dir] && y == pre_y + fy[dir])
            return false;
        pre_x = pre_x + fx[dir], pre_y = pre_y + fy[dir];
    }
    return true;
}

void BFS()
{
    State a;
    int dx, dy, s;
    while(!Q.empty())
    {
        a = Q.front();
        Q.pop();
        for(int i = 0; i < 4; i++)
        {
            dx = a.x + fx[i], dy = a.y + fy[i];
            s = get_next_state(i, a.s);
            if(dx > 0 && dy > 0 && dx <= N && dy <= M && !vis[dx][dy][s] && !_map[dx][dy] && judge_code(dx, dy, a.x, a.y, a.s))
            {
                if(dx == 1 && dy == 1)
                {
                    res = a.dis + 1;
                    return ;
                }
                vis[dx][dy][s] = 1;
                Q.push(State(dx, dy, a.dis + 1, s));
            }
        }
    }
}

int main()
{
    int s = 0, _case = 0;
    State _start;
    while(scanf("%d%d%d", &N, &M, &L), N + M + L)
    {
        res = INF;
        memset(_map, 0 , sizeof(_map));
        memset(vis, 0 , sizeof(vis));
        for(int i = 0; i < L; i++)
            scanf("%d%d", &pos[i].x, &pos[i].y);
        int K, u, v;
        scanf("%d", &K);
        for(int i = 0; i < K; i++)
        {
            scanf("%d%d", &u, &v);
            _map[u][v] = 1;
        }
        if(pos[0].x == 1 && pos[0].y == 1)
        {
            printf("Case %d: 0\n", ++_case);
            continue;
        }
        s = get_start();
        Q.push(State(pos[0].x, pos[0].y, 0, s));
        vis[pos[0].x][pos[0].y][s] = 1;
        BFS();
        if(res == INF)
            printf("Case %d: -1\n", ++_case);
        else
            printf("Case %d: %d\n", ++_case, res);
        while(!Q.empty())
            Q.pop();
    }
    return 0;
}



标签:pre,&&,1324,int,BFS,poj,dx,dy,dir
From: https://blog.51cto.com/u_16143128/6373670

相关文章

  • poj 1195(二维树状数组)
    解题思路:这是一道很裸的二维树状数组AC:#include<stdio.h>#include<string.h>#defineN1100intc[N][N],n,arr[N][N];intlowbit(intx){returnx&(-x);}voidupdate(intx,inty,intnum){inti,j;for(i=x;i<=n;i+=lowbit(i))for(j=y;......
  • POJ 1505(二分+贪心)
    题意:给一些书,这些书有不同的页数,让把这些书分成k份,必须是连续的,问这些份中页数和的最大值最小是多少。解题思路:知道了页数和的范围,而且书都是连续的,要找到页数和最大值的最小值可以直接二分答案。。AC:#include<iostream>#include<cstdlib>#include<cstring>usingnamespacestd......
  • poj 3411(DFS多点访问)
    题意:有n座城市和m(1<=n,m<=10)条路。现在要从城市1到城市n。有些路是要收费的,从a城市到b城市,如果之前到过c城市,那么只要付P的钱,如果没有去过就付R的钱。求的是最少要花多少钱。解题思路:这道题的n与m都很小,dfs可以搞定,但这里与以往的搜索不同,以前dfs每个节点只能够访问一次,这里有多次访......
  • POJ 1797 Heavy Transportation(迪杰斯特拉最短路变形)
    传送门题意分析:Hugo想要扩展他的公司,他有起重机要到目的地,到达目的地有很多条路径,但是,每一条路都有相应承重量,现在需要找出到达目的地的最大承重道路的承重质量。解题分析:首先,每一条路径的承重量取决于承重量最小的那条道路(短板效应),所以就是找所有路径的最小值,然后选择最小值最大的......
  • POJ 1753 Flip Game(枚举+递归)
    传送门思路是别人的,自己理解了半天,真是渣渣。对于自己,路还长,年轻人。对任意一个格子来说,翻动偶数次等于没翻,翻动奇数次等于翻一次,所以只需考虑翻一次的情况。一共16个格子,每个格子只有翻和不翻,所以最多16步,最少0步,题目要求最少的步数,所以0——>16枚举,看哪一步先成功就是最优解。使......
  • POJ 3069 Saruman's Army(贪心)
    传送门这个题是说给你n个点,然后让你标记其中尽可能少的点,使得n个点都处于被标记点左右不超过R的区间内我们使用的是贪心算法,也就是我们要将被标记的点尽可能的朝右边去即可,首先我们将他们从左到右进行排序,第一个我们所选取的被标记的点应该是能够包含掉左边的点的最靠右的点。。。......
  • POJ 1182 食物链
    解题思路:并查集经典中的经典题,在网上看了很多大牛的思路,大部分是增加一个结构体存动物间的关系,结合并查集判断,但是关系域的更新比较复杂,一下子不太容易理解。所以就有人另开思路,这里介绍一个十分巧妙的思路。一般我们都会把一个动物当成一个节点,然后去执行并查集等操作。但是有位大......
  • POJ 2251 Dungeon Master(三维BFS)
    题目看起来很厉害,实际上看懂了并不难,开一个三维的数组,这里需要注意的是第一维是高度,然后就是简单的BFS了,还有不同就是三维的时候有六个方向可以走,在前后左右的基础上多了一个向上和向下的走法,还有一个问题就是多个输入样例要注意每次都要初始化,我做的时候就因为这个WA了好几次,最后......
  • POJ 2080 Calendar
    题目链接:http://poj.org/problem?id=2080题目不是很难,也没什么说的,直接看代码吧:#include<iostream>#include<stdio.h>usingnamespacestd;intyear(intm){ if(m%4==0&&m%100!=0||m%400==0) return1; else return0;}intmain(){ intn,i,j......
  • 区分PO、VO、 BO、 DTO、 POJO
     分层领域模型规约:DO(DataObject):此结构与数据库表结构一一对应,通过DTO向上传输数据源对象。DTO(DataTransferObject):数据传输对象,Service或Manager向外传输的对象。BO(BusinessObject):业务对象,由Service层输出的封装业务逻辑的对象。AO(ApplicationObject):应用......