zoukankan      html  css  js  c++  java
  • [BZOJ1556]墓地秘密

    [BZOJ1556]墓地秘密

    试题描述

    费尽周折,终于将众将士的残骸运送到了KD军事基地地底层的大型墓地入口。KD的伙伴和战友们都参加了这次重大的送葬仪式。右边是一扇敞开的大门,进去便是墓地了,左边是一堵凹进去的墙,没有什么特别的地方。 部队缓缓进入右边的门,一切。。。就这么结束了么。。。。。 此时, F却没有跟上队伍,在一般MM都会有的强烈的第六感之下,她来到了左边这堵墙前一探究竟。扫去了重重的灰尘之后,墙上一块凹进去的手掌印清晰可见了。F试着用自己的手对上去,竟刚好合适。稍微用力一按,顿时一声巨响,地上马上裂开一大洞,F和那厚重的墙瞬间一起落入深渊!当其他人听见了巨大的声响而赶来的时候,一切都恢复平静了。只有那堵墙后面的世界,震惊了所有生物。这到底是什么,为什么会在墓地里面? 墙的后面是一个巨大的迷宫!简单的一行字浮现在了一侧的墙上:猛烈撞击所有发亮的机关石。当大伙好奇的蜂拥进迷宫的时候,一块莫名其妙的巨石竟从入口上方落下,将入口完全堵死了!石头上清晰的写了一行字:超过规定时间不能完成任务,全部人都会困死于此。看来,只有硬着头皮去闯,才有可能离开这里,并且探索出这个迷宫的秘密了。 于是大家马上散开,很快摸清了这里的地形,剩下的任务就是轰击石头了。那么。。。论攻击力最高的,自然非功夫DP莫属,而且功夫DP可以使用前滚翻移动法,能够瞬间获得巨大的初速度,并且在直线运动的时候速度将近似光速,质量无穷大,那动能自然就。。。。。。DP每次可以选择朝一个方向滚动,并且可以自己选择在某位置停下来,或者撞击到墙和石头的时候被迫停下来。由于直线速度过快,所以要停下来拐弯自然就是很麻烦的事情。那么只有制定出一个最好的运动方法,使得DP停下来次数最少,才能争取尽量多的时间!

    输入

    第一行3个正整数N、M和T。表示这是一个N*M的迷宫,并且有T个机关石。 接下来用一个N*M的字符矩阵描述迷宫,.表示是空地,#表示是墙。 接下来T行每行2个正整数X、Y,描述一个机关石的位置,它在迷宫对应的位置是#。不会有两个机关石在同一位置。 最后一行2个正整数X0、Y0,表示DP的初始位置。

    输出

    一个正整数ANS,表示DP至少要停下来多少次才能撞击完所有的机关石。

    输入示例

    4 6 3
    ......
    ....#.
    .....#
    ....#.
    2 5
    3 6
    4 5
    1 5

    输出示例

    5

    数据规模及约定

    对于10%的数据,N、M<=10,T<=2;
    对于40%的数据,N、M<=50,T<=10;
    对于100%的数据,N、M<=100,T<=15;

    题解

    我们只需要关心所有“机关石”上下左右的位置(不妨称这些位置为“关键点”),所以我们可以从这些位置开始依次 BFS 一遍处理出每两个关键点之间的最少停顿次数,这个 BFS 就可以设 (x, y, dir) 为一个状态表示处在地图的 (x, y) 坐标,当前方向为 dir(0~4 为上下左右,5 为停),然后每次转移可能 +0 或者 +1,我们开一个双头队列,把 +0 扔到前面,+1 的扔到后面,每次取状态时从前面取就好了。

    接下来就是 dp 了,我们设 f(S, i) 表示已经撞过的机关石的集合为 S,当前在第 i 个关键点,然后枚举下一次去哪个关键点转移就好了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 110
    #define maxs 32770
    #define maxk 65
    #define oo 2147483647
    
    int n, m, K;
    char Map[maxn][maxn];
    
    struct Point {
    	int x, y;
    	Point() {}
    	Point(int _, int __): x(_), y(__) {}
    } ps[maxk];
    
    struct Sta {
    	int x, y, dir;
    	Sta() {}
    	Sta(int _1, int _2, int _3): x(_1), y(_2), dir(_3) {}
    } at[maxk];
    int cntat, stid[maxk];
    
    bool inside(int x, int y) { return 1 <= x && x <= n && 1 <= y && y <= m && Map[x][y] != '#'; }
    
    int dx[5] = {0, 0, -1, 1, 0}, dy[5] = {-1, 1, 0, 0, 0};
    #define left 0
    #define right 1
    #define up 2
    #define down 3
    #define stop 4
    const char* Dir(int x) {
    	if(x == 0) return "left";
    	if(x == 1) return "right";
    	if(x == 2) return "up";
    	if(x == 3) return "down";
    	return "stop";
    }
    
    int d[maxn][maxn][5], dis[maxk][maxk];
    deque <Sta> Q;
    void solve(Sta s, int a) {
    	memset(d, -1, sizeof(d));
    	d[s.x][s.y][s.dir = stop] = 0;
    	Q.push_front(s);
    //	if(a == 8) printf("s: %d %d %s
    ", s.x, s.y, Dir(s.dir));
    	while(!Q.empty()) {
    		Sta u = Q.front(), v; Q.pop_front();
    //		if(a == 8) printf("u: %d %d %s %d %d
    ", u.x, u.y, Dir(u.dir), d[u.x][u.y][u.dir], vis[u.x][u.y][u.dir]);
    		int now = d[u.x][u.y][u.dir];
    		if(u.dir == stop) {
    			v = u;
    			for(int i = 0; i < 4; i++) {
    				if(d[v.x][v.y][i] < 0) {
    //					if(a == 8) printf("v: %d %d %s %d
    ", v.x, v.y, Dir(v.dir), d[v.x][v.y][stop]);
    					v.dir = i; Q.push_front(v);
    					d[v.x][v.y][i] = now;
    				}
    			}
    		}
    		else {
    			v = u;
    //			printf("v: %d %d %s %d
    ", v.x, v.y, Dir(v.dir), d[v.x][v.y][stop]);
    			if(d[v.x][v.y][stop] < 0) {
    				v.dir = stop; Q.push_back(v);
    				d[v.x][v.y][stop] = now + 1;
    			}
    			v = u;
    			v.x += dx[v.dir]; v.y += dy[v.dir];
    			if(inside(v.x, v.y) && d[v.x][v.y][v.dir] < 0) {
    				Q.push_front(v);
    				d[v.x][v.y][v.dir] = now;
    			}
    		}
    	}
    	for(int i = 1; i <= cntat; i++) dis[a][i] = d[at[i].x][at[i].y][at[i].dir];
    	return ;
    }
    
    int f[maxs][maxk];
    void upd(int& a, int b) {
    	a = min(a, b);
    	return ;
    }
    
    int main() {
    	n = read(); m = read(); K = read();
    	for(int i = 1; i <= n; i++) scanf("%s", Map[i] + 1);
    	for(int i = 1; i <= K; i++) {
    		ps[i].x = read(); ps[i].y = read();
    	}
    	ps[K+1].x = read(); ps[K+1].y = read();
    	
    	for(int i = 1; i <= K; i++) {
    		if(inside(ps[i].x - 1, ps[i].y)) at[++cntat] = Sta(ps[i].x - 1, ps[i].y, down), stid[cntat] = i - 1;
    		if(inside(ps[i].x + 1, ps[i].y)) at[++cntat] = Sta(ps[i].x + 1, ps[i].y, up), stid[cntat] = i - 1;
    		if(inside(ps[i].x, ps[i].y - 1)) at[++cntat] = Sta(ps[i].x, ps[i].y - 1, right), stid[cntat] = i - 1;
    		if(inside(ps[i].x, ps[i].y + 1)) at[++cntat] = Sta(ps[i].x, ps[i].y + 1, left), stid[cntat] = i - 1;
    	}
    	at[++cntat] = Sta(ps[K+1].x, ps[K+1].y, stop);
    	for(int i = 1; i <= cntat; i++) solve(at[i], i);
    	
    	/*for(int i = 1; i <= cntat; i++) printf("%d: %d %d %s
    ", i, at[i].x, at[i].y, Dir(at[i].dir));
    	for(int i = 1; i <= cntat; i++)
    		for(int j = i + 1; j <= cntat; j++) printf("%d to %d: %d
    ", i, j, dis[i][j]); // */
    	int all = (1 << K) - 1;
    	for(int S = 0; S <= all; S++)
    		for(int i = 1; i < cntat; i++) f[S][i] = oo;
    	for(int i = 1; i < cntat; i++) if(dis[cntat][i] >= 0) f[1<<stid[i]][i] = dis[cntat][i] + 1;
    	for(int S = 0; S <= all; S++)
    		for(int i = 1; i < cntat; i++) if(f[S][i] < oo)
    			for(int j = 1; j < cntat; j++) if(i != j && dis[i][j] >= 0)
    				upd(f[S|(1<<stid[j])][j], f[S][i] + dis[i][j] + 1);
    	
    	int ans = oo;
    	for(int i = 1; i < cntat; i++) upd(ans, f[all][i]);
    	printf("%d
    ", ans);
    	
    	return 0;
    }
    
  • 相关阅读:
    SecureCRT安装
    wmv12下安装centos7
    SpringMVC(十二):SpringMVC 处理输出模型数据之@ModelAttribute
    oracle之 redo过高诊断
    oracle之 手动创建 emp 表 与 dept 表
    oracle之 11.2.0.4 bbed安装
    oracle12c之 控制pdb中sga 与 pga 内存使用
    storm之 Storm 工作原理
    spark之 spark 2.2.0 Standalone安装、wordCount演示
    hadoop之 参数调优
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6637931.html
Copyright © 2011-2022 走看看