hdu 5025 BFS + 优化 广东区域赛网赛

http://acm.hdu.edu.cn/showproblem.php?pid=5025

TLE了好几次

写的时候,问题在于,

1、钥匙怎么处理

参考了他人的写法,vis[key_num][i][j],相当于将图多维化,这样就可以判重了,否则只是按照普通的BFS,钥匙数不同的时候,可以重复,这个代码难易表达出来

另外此处一个很好的优化,当cost_now<cost[key_now][x_now][y_now]的时候,才q.push(Node)  这个剪枝很好啊

2、蛇怎么处理

没蛇的话,第一次搜到的可行解就是最优解,

有蛇的话,需要解决1、第一次遇到蛇杀死,以后遇到不杀,这个用set存储,每次find,注意只把曾经有蛇的地方insert,因为蛇只有5个,所以这个空间是开的下的,时间也承受的住  2、彻底将图搜完才可以结束搜索

//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const double EPS = 1e-8;
const double pi = acos(-1.0);
const int INF = 100000000;
const int MAXN = 100+10;

int n,m,kx,ky,tx,ty;
char mat[MAXN][MAXN];
int vis[10][MAXN][MAXN];

struct Node{
    int x,y,k,cost;
    Node(){};
    Node(int xx,int yy,int kk, int cc){x=xx;y=yy;k=kk;cost=cc;}
    set< pair<int, int> >s;
};

int dir[4][2]={ {-1,0},{0,-1},{1,0},{0,1} };
queue<Node>q;

bool legal(int x, int y)
{
    if(x>=0 && y>=0 && x<n && y<n)return 1;
    else return 0;
}

int bfs()
{
    int ret=INF;
    q.push( Node(kx,ky,0,0) );
    CL(vis,0xff);
    while(!q.empty())
    {
        Node tmp=q.front();q.pop();
        for(int i=0;i<4;i++)
        {
            int x=tmp.x+dir[i][0];
            int y=tmp.y+dir[i][1];
            if(mat[x][y]=='#' ||  !legal(x,y))continue;
            Node nxt=tmp;
            nxt.x=x;
            nxt.y=y;
            nxt.cost++;
            if(mat[x][y] >= '1' && mat[x][y] <='9')
            {
                int num=mat[x][y]-'1';
                if(num == tmp.k)
                {
                    nxt.k=num+1;
                }
            }
            if(mat[x][y] == 'S' && tmp.s.find(make_pair(x,y)) == tmp.s.end())
            {
                nxt.cost++;
                nxt.s.insert(make_pair(x,y));
            }
            if(vis[nxt.k][x][y]>nxt.cost || vis[nxt.k][x][y]==-1)
            {
                vis[nxt.k][x][y]=nxt.cost;
                q.push(nxt);
            }
        }
    }
    return vis[m][tx][ty];
}

int main()
{
    //IN("hdu5025.txt");
    while(~scanf("%d%d",&n,&m) && n+m)
    {
        getchar();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                mat[i][j]=getchar();
                if(mat[i][j] == 'K'){kx=i;ky=j;}
                if(mat[i][j] == 'T'){tx=i;ty=j;}
            }
            getchar();
        }
        while(!q.empty())q.pop();
        int ans=bfs();
        if(ans == -1)printf("impossible\n");
        else printf("%d\n",bfs());
    }
    return 0;
}
时间: 2024-10-18 16:47:43

hdu 5025 BFS + 优化 广东区域赛网赛的相关文章

HDU 5025 (BFS+记忆化状压搜索)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5025 题目大意: 迷宫中孙悟空救唐僧,可以走回头路.必须收集完钥匙,且必须按顺序收集.迷宫中还有蛇,杀蛇多耗时1,蛇杀完就没了.问最少耗时. 解题思路: 2014广州网赛的水题之一.当时没刷过BFS状压,结果悲剧了. 首先这题可以压钥匙,也可以压蛇,不过压钥匙内存岌岌可危,于是就压蛇吧. 设f[x][y][key][snake]为在(x,y)点,已经取得的钥匙key,以及杀蛇snake的状态. 对

HDU 5025 Saving Tang Monk(广州网络赛D题)

HDU 5025 Saving Tang Monk 题目链接 思路:记忆化广搜,vis[x][y][k][s]表示在x, y结点,有k把钥匙了,蛇剩余状态为s的步数,先把图预处理出来,然后进行广搜即可 代码: #include <cstdio> #include <cstring> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int N = 105; const int

hdu 5023 线段树 区间 2014广东区域赛网赛

http://acm.hdu.edu.cn/showproblem.php?pid=5023 当时大一学弟15minAC 搞得我压力山大 给队友写了 今天重新做了下,题还是很水  但是因为pushdown的时候if(l==r)return没有写  WA了一次 感觉到现在,简单的线段树已经可以随意点写了,就是按照自己的理解写,别慌,错了按树的结构思考下重新写 查询不知道pushdown所有的会不会超时,我的还是区间的查询,凡是子区间被修改过的结点,该节点pushdown后 其co值都被我改为0 然

HDU 5025 BFS+状压

2014 ACM/ICPC Asia Regional Guangzhou Online N*N矩阵 M个钥匙 K起点,T终点,S点需多花费1点且只需要一次,1-9表示9把钥匙,只有当前有I号钥匙才能拿I+1号钥匙,可以不拿钥匙只从上面走过 4维数组判重,第三维表示钥匙已经拿到第几把,第四维表示已经走过的S的状况,用状压存储 #include "stdio.h" #include "string.h" #include "queue" using

zoj 3809 水 2014 ACM牡丹江区域赛网赛

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5341 第一题水题,水下 //#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <ios

HDU 4791 Alice&#39;s Print Service(2013长沙区域赛现场赛A题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4791 解题报告:打印店提供打印纸张服务,需要收取费用,输入格式是s1 p1 s2 p2 s3 p3...表示打印区间s1到s2张纸的单价是p1,打印区间s2 到s3的单价是p2....最后是sn到无穷大的单价是pn,让你求打印k张纸的总费用最少是多少?有m次查询. 因为s1*p1 > s2 * p2 > s3*p3......,很显然,加入k所在的那个区间是第x个区间,那么最低费用要么是k * p

ACM学习历程—HDU 5023 A Corrupt Mayor&#39;s Performance Art(广州赛区网赛)(线段树)

Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this seemed a safe way for mayor X to make money. Becaus

HDU 1072 bfs

Nightmare Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7083    Accepted Submission(s): 3409 Problem Description Ignatius had a nightmare last night. He found himself in a labyrinth with a tim

hdu 1429 bfs+状压

题意:这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方.刚开始 Ignatius被关在(sx,sy)的位置,离开地牢的门在(ex,ey)的位置.Ignatius每分钟只能从一个坐标走到相邻四个坐标中的其中一 个.魔王每t分钟回地牢视察一次,若发现Ignatius不在原位置便把他拎回去.经过若干次的尝试,Ignatius已画出整个地牢的地图.现在请你帮 他计算能否再次成功逃亡.只要在魔王下次视察之前走到出口就算离开地牢