【POJ】3523 The Morning after Halloween
1. 题目描述
$m \times n$的迷宫(最大为$16 \times 16$)包含最多3个点,这些点可以同时向相邻方向移动或保持停止,使用小写字母表示起始位置,使用大写字母表示中止位置。求最少经过多少时间,这些点可以从起始位置移动到对应的终止位置。
2. 基本思路
这是很经典的路径搜索问题,一般采用BFS。因为题目说每个$2 \times 2$个子矩阵,都至少有一个点为#,那么起始空白可走的点一定很少,因此,可以预处理这些点可以通过1个时间单位到达的有效位置。这样可以降低$5^3$的总排列。显然,同时对三个点组成的三元组进行状态压缩,这里采用移位。这些做完了,普通的BFS+map就已经可以解出正确解了。但是太慢了。因此,使用双向BFS+map,发现还是超时,原因是map太慢了(而且会随着状态的增加越来越慢)。那么,直接用数组存(注意不要MLE)。直接过了。双向BFS明显地提高了性能。
3. 代码
/* 3523 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <bitset>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
#define INF 0x3f3f3f3f
#define mset(a, val) memset(a, (val), sizeof(a)) const int maxn = ;
const int maxm = ;
int ID[maxn][maxn];
int sz[maxm];
int Move[maxm][];
int visit[][maxm][maxm][maxm];
char s[maxn][maxn];
map<char,int> ptb;
queue<int> Q[];
int dir[][] = {
-, , , , , -, , , ,
};
int n, m, gn;
int st, ed; inline bool judge(int x, int y) {
return x< || x>=n || y< || y>=m || s[x][y]=='#';
} void init() {
int cnt = ;
map<char,int>::iterator iter; ptb.clr(); rep(i, , n) {
rep(j, , m) {
if (s[i][j] == '#')
continue; ID[i][j] = cnt++;
if (s[i][j] != ' ')
ptb[s[i][j]] = ID[i][j];
}
} rep(i, , n) {
rep(j, , m) {
if (s[i][j] == '#')
continue; const int& id = ID[i][j];
sz[id] = ;
Move[id][] = id;
rep(k, , ) {
int x = i + dir[k][];
int y = j + dir[k][];
if (judge(x, y))
continue; Move[id][sz[id]++] = ID[x][y];
}
}
} st = ed = ; for (char ch='a'; ch<='z'; ++ch) {
iter = ptb.find(ch);
if (iter != ptb.end()) {
st = (st << ) | iter->sec;
iter = ptb.find(ch-'a'+'A');
#ifndef ONLINE_JUDGE
assert(iter != ptb.end());
#endif
ed = (ed << ) | iter->sec;
}
}
} int bfs1(const int qid) {
int cst, nst;
int qsz = SZ(Q[qid]); while (qsz--) {
cst = Q[qid].front();
Q[qid].pop(); int step = visit[qid][][][cst] + ;
rep(i, , sz[cst]) {
nst = Move[cst][i];
if (visit[qid][][][nst] == -) {
if (visit[qid^][][][nst] >= )
return step + visit[qid^][][][nst];
visit[qid][][][nst] = step;
Q[qid].push(nst);
}
}
} return -;
} int bfs2(const int qid) {
int cst[], nst[], tmp;
int qsz = SZ(Q[qid]); while (qsz--) {
st = Q[qid].front();
Q[qid].pop(); per(i, , ) {
cst[i] = st & 0xff;
st >>= ;
} int step = visit[qid][][cst[]][cst[]] + ; rep(i, , sz[cst[]]) {
nst[] = Move[cst[]][i];
rep(j, , sz[cst[]]) {
nst[] = Move[cst[]][j];
if (nst[]==nst[] || (nst[]==cst[]&&nst[]==cst[]))
continue; tmp = nst[]<< | nst[];
if (visit[qid][][nst[]][nst[]] == -) {
if (visit[qid^][][nst[]][nst[]] != -)
return step + visit[qid^][][nst[]][nst[]];
visit[qid][][nst[]][nst[]] = step;
Q[qid].push(tmp);
}
}
}
} return -;
} inline bool check(int *nst, int *cst) {
return (nst[]==cst[] && nst[]==cst[]) || (nst[]==cst[] && nst[]==cst[]) || (nst[]==cst[] && nst[]==cst[]);
} int bfs3(const int qid) {
int cst[], nst[], tmp;
int qsz = SZ(Q[qid]); while (qsz--) {
st = Q[qid].front();
Q[qid].pop(); per(i, , ) {
cst[i] = st & 0xff;
st >>= ;
} int step = visit[qid][cst[]][cst[]][cst[]] + ; rep(i, , sz[cst[]]) {
nst[] = Move[cst[]][i];
rep(j, , sz[cst[]]) {
nst[] = Move[cst[]][j];
rep(k, , sz[cst[]]) {
nst[] = Move[cst[]][k];
if (nst[]==nst[] || nst[]==nst[] || nst[]==nst[] || check(cst, nst))
continue; tmp = (nst[]<<) | (nst[]<<) | (nst[]); if (visit[qid][nst[]][nst[]][nst[]] == -) {
if (visit[qid^][nst[]][nst[]][nst[]] != -)
return step + visit[qid^][nst[]][nst[]][nst[]];
visit[qid][nst[]][nst[]][nst[]] = step;
Q[qid].push(tmp);
}
}
}
}
} return -;
} #define bibfs(n)\
int bibfs##n() {\
int tmp; \
\
while (!Q[].empty() || !Q[].empty()) {\
tmp = bfs##n();\
if (tmp >= ) return tmp;\
tmp = bfs##n();\
if (tmp >= ) return tmp;\
}\
\
return -;\
} #define callbibfs(n) bibfs##n() bibfs()
bibfs()
bibfs() void solve() {
init();
int ans; memset(visit, -, sizeof(visit));
rep(i, , )
while (!Q[i].empty()) Q[i].pop();
visit[][st>>][(st>>)&0xff][st&0xff] = ;
visit[][ed>>][(ed>>)&0xff][ed&0xff] = ;
Q[].push(st);
Q[].push(ed); if (gn == ) {
ans = callbibfs();
} else if (gn == ) {
ans = callbibfs();
} else {
ans = callbibfs();
} printf("%d\n", ans);
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif while (scanf("%d%d%d%*c",&m,&n,&gn)!=EOF && (n||m||gn)) {
rep(i, , n)
gets(s[i]);
solve();
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}
【POJ】3523 The Morning after Halloween的更多相关文章
- 【POJ】1704 Georgia and Bob(Staircase Nim)
Description Georgia and Bob decide to play a self-invented game. They draw a row of grids on paper, ...
- 【POJ】1067 取石子游戏(博弈论)
Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后 ...
- 【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉
DP/单调队列优化 首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b \leq k \leq i-2*a $ 当然这里的$i$和$k$都是偶数啦~ ...
- 【POJ】【2104】区间第K大
可持久化线段树 可持久化线段树是一种神奇的数据结构,它跟我们原来常用的线段树不同,它每次更新是不更改原来数据的,而是新开节点,维护它的历史版本,实现“可持久化”.(当然视情况也会有需要修改的时候) 可 ...
- 【POJ】1222 EXTENDED LIGHTS OUT
[算法]高斯消元 [题解] 高斯消元经典题型:异或方程组 poj 1222 高斯消元详解 异或相当于相加后mod2 异或方程组就是把加减消元全部改为异或. 异或性质:00 11为假,01 10为真.与 ...
- 【POJ】2892 Tunnel Warfare
[算法]平衡树(treap) [题解]treap知识见数据结构 在POJ把语言从G++换成C++就过了……??? #include<cstdio> #include<algorith ...
- 【POJ】【1637】Sightseeing tour
网络流/最大流 愚人节快乐XD 这题是给一个混合图(既有有向边又有无向边),让你判断是否有欧拉回路…… 我们知道如果一个[连通]图中每个节点都满足[入度=出度]那么就一定有欧拉回路…… 那么每条边都可 ...
- 【poj】1001
[题目] ExponentiationTime Limit: 500MS Memory Limit: 10000KTotal Submissions: 123707 Accepted: 30202De ...
- 【POJ】3070 Fibonacci
[算法]矩阵快速幂 [题解] 根据f[n]=f[n-1]+f[n-2],可以构造递推矩阵: $$\begin{vmatrix}1 & 1\\ 1 & 0\end{vmatrix} \t ...
随机推荐
- mysql简单操作一
MySQL的一些简单管理: 启动MySQL服务: sudo start mysql 停止MySQL服务: sudo stop mysql 修改 MySQL 的管理员密码: sudo mysqladmi ...
- Log4Net学习【一】
如果项目上过线的话,那你一定知道Log是多么重要.为什么说Log重要呢?因为上线项目不允许你调试,你只能通过Log来分析问题.这时打一手好Log的重要性绝不亚于写一手好代码.项目出问题时,你要能拿出L ...
- extern "C"——用“C”来规约在C++中用C的方式进行编译和链接
C++中的extern “C”用法详解 extern "C"表明了一种编译规约,其中extern是关键字属性,“C”表征了编译器链接规范.对于extern "C& ...
- 保持程序在后台长时间运行-b
iOS为了让设备尽量省电,减少不必要的开销,保持系统流畅,因而对后台机制采用墓碑式的“假后台”.除了系统官方极少数程序可以真后台,一般开发者开发出来的应用程序后台受到以下限制:1.用户按Home之后, ...
- iOS10.0 TabBar Bug(底部同时展示原生和自定义tabBar)-b
在没有发布iOS10的时候,在任何模拟器测试下效果正常,更新iOS10后,测试出现BUG先放一张bug之前的效果图: 修改前出现的bug 在检查了所有问题之后,最后把问题定位在了原生系统tabBar底 ...
- 3573: [Hnoi2014]米特运输 - BZOJ
Description米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. D星上有N个城市,我们将其顺序编号为1到N,1号 ...
- IOS7 适配时导航栏变黑
当适配IOS的布局时遇到问题:导航栏和菜单栏后台会变黑色. self.edgesForExtendedLayout = UIRectEdgeNone; 原因是系统默认这两个控件是半通明的. 解决方案: ...
- 【BZOJ】【1029】【JSOI2007】建筑抢修
贪心 按T2(完成时限)排序,然后从前往后依次枚举 如果sum+a[i].t1<=a[i].t2则加入 如果来不及修这个建筑: 如果当前这个建筑的维修时间t1比之前修过的建筑中耗时最长的耗时短, ...
- crontab定时运行git命令 更新代码库
Q: http://stackoverflow.com/questions/7994663/git-push-via-cron I'm trying to run a git push fro ...
- POJ 1062 昂贵的聘礼(Dijkstra)
题意 : 真真是做POJ第一次遇到中文题,好吧,虽然语言通了,我一开始也没看懂样例什么意思,题意的话就是说这个探险家想娶酋长的女儿,但是没有钱,酋长说他可以用祭司的水晶球或者皮袄来换取少花一部分钱,同 ...