HDU 5040 Instrusive(北京网络赛I题)

HDU 5040 Instrusive

题目链接

思路:记忆化广搜,先预处理出图,每个位置用一个二进制数表示,表示4秒为1个周期内,这个位置是否会被照到,然后进行记忆化广搜即可,状态多开一个4,表示在4秒一周期,然后进行转移即可

代码:

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

const int N = 505;
const int d[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};

int t, n;
int g[N][N], vis[N][N][5];

struct State {
	int x, y, t;
	State() {}
	State(int x, int y, int t) {
		this->x = x;
		this->y = y;
		this->t = t;
	}
} s, e;

int get(char c) {
	if (c == 'N') return 0;
	if (c == 'E') return 3;
	if (c == 'S') return 2;
	if (c == 'W') return 1;
	return -1;
}

const int INF = 0x3f3f3f3f;
char str[N][N];

int solve() {
	queue<State> Q;
	Q.push(s);
	memset(vis, INF, sizeof(vis));
	vis[s.x][s.y][s.t] = 0;
	while (!Q.empty()) {
		State u = Q.front();
		Q.pop();
		State v = u;
		v.t = (v.t + 1) % 4;
		if (vis[v.x][v.y][v.t] > vis[u.x][u.y][u.t] + 1) {
			vis[v.x][v.y][v.t] = vis[u.x][u.y][u.t] + 1;
			Q.push(v);
		}
		for (int i = 0; i < 4; i++) {
			State v = u;
			v.x = u.x + d[i][0];
			v.y = u.y + d[i][1];
			int add = 0;
			if (v.x < 0 || v.x >= n || v.y < 0 || v.y >= n || g[v.x][v.y] == -1) continue;
			if ((g[u.x][u.y]&(1<<u.t)) || (g[v.x][v.y]&(1<<u.t))) {
				v.t = (v.t + 3) % 4;
				add = 3;
			} else {
				v.t = (v.t + 1) % 4;
				add = 1;
			}
			if (vis[v.x][v.y][v.t] > vis[u.x][u.y][u.t] + add) {
				vis[v.x][v.y][v.t] = vis[u.x][u.y][u.t] + add;
				Q.push(v);
			}
		}
	}
	int ans = INF;
	for (int i = 0; i < 4; i++)
		ans = min(ans, vis[e.x][e.y][i]);
	if (ans == INF) ans = -1;
	return ans;
}

int main() {
	int cas = 0;
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
			scanf("%s", str[i]);
		memset(g, 0, sizeof(g));
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (str[i][j] == 'M')
					s = State(i, j, 0);
				else if (str[i][j] == 'T')
					e = State(i, j, 0);
				else if (str[i][j] == '#')
					g[i][j] = -1;
				else if (str[i][j] == 'N' || str[i][j] == 'E' || str[i][j] == 'S' || str[i][j] == 'W') {
					g[i][j] = 15;
					for (int k = 0; k < 4; k++) {
						int x = i + d[k][0];
						int y = j + d[k][1];
						if (x < 0 || x >= n || y < 0 || y >= n || str[x][y] == '#') continue;
						g[x][y] |= (1<<((get(str[i][j]) + k) % 4));
					}
				}
			}
		}
		printf("Case #%d: %d\n", ++cas, solve());
	}
	return 0;
}
时间: 2024-10-27 17:37:30

HDU 5040 Instrusive(北京网络赛I题)的相关文章

2015北京网络赛A题The Cats&#39; Feeding Spots

题意:给你一百个点,找个以这些点为中心的最小的圆,使得这个圆恰好包含了n个点,而且这个圆的边界上并没有点 解题思路:暴力枚举每个点,求出每个点到其他点的距离,取第n大的点,判断一下. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<memory.h> 6 using namespace std; 7 const i

HDU 5033 Building(北京网络赛B题) 单调栈 找规律

做了三天,,,终于a了... 11724203 2014-09-25 09:37:44 Accepted 5033 781MS 7400K 4751 B G++ czy Building Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1257    Accepted Submission(s): 358 Special Judg

HDU 5033 Building(北京网络赛B题)

HDU 5033 Building 题目链接 思路:利用单调栈维护建筑建的斜线,保持斜率单调性,然后可以把查询当成高度为0的建筑,和建筑和在一起考虑,从左往右和从右往左各扫一遍即可 代码: #include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <algorithm> using namespace std; const int N = 200

HDU 5036 Explosion(北京网络赛E题)

HDU 5036 Explosion 题目链接 思路:对于每个点,只要考虑哪些炸掉能到他的个数cnt,那么他对应的期望就是1 / cnt,然后所以期望的和就是答案,用bitset来维护 代码: #include <cstdio> #include <cstring> #include <bitset> using namespace std; const int N = 1005; int t, n; bitset<N> bs[N]; int main()

HDU 6205 2017沈阳网络赛 思维题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6205 题意:给你n堆牌,原本每一堆的所有牌(a[i]张)默认向下,每次从第一堆开始,将固定个数的牌(b[i]张)翻上,然后下一堆继续,直到没有足够的牌翻上,然后你可以获得当前已经操作过的堆的所有牌.最初你可以调整堆的顺序,把第一堆放到最后一堆(逆时针旋转),你可以重复这个操作,问你要重复多少次这个操作,才能获得最多的牌. 解法:先把这个序列复制一遍放在原来的序列后面.当i=n的时候结束就可以了,每次

(中等) Hiho 1232 Couple Trees(15年北京网络赛F题),主席树+树链剖分。

"Couple Trees" are two trees, a husband tree and a wife tree. They are named because they look like a couple leaning on each other. They share a same root, and their branches are intertwined. In China, many lovers go to the couple trees. Under t

hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题

题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给定的学生成绩都异或上一次的答案 先将学生按每一门成绩都排一次序 这里将学生分块成sqrt(n)的块数,然后在当前块中用bitset容器来记录含有学生的状态 这里可以记录状态的前缀和,因为比后面成绩好的,必然比前面的学生的成绩也好 查询的时候只要查到正好比他高的学生属于哪一块,这样只要访问sqrt(n

hdu 5446(2015长春网络赛J题 Lucas定理+中国剩余定理)

题意:M=p1*p2*...pk:求C(n,m)%M,pi小于10^5,n,m,M都是小于10^18. pi为质数 M不一定是质数 所以只能用Lucas定理求k次 C(n,m)%Pi最后会得到一个同余方程组x≡B[0](mod p[0])x≡B[1](mod p[1])x≡B[2](mod p[2])......解这个同余方程组 用中国剩余定理 Sample Input19 5 23 5 Sample Output6 1 # include <iostream> 2 # include <

hdu 5112 (2014北京区域赛 A题)

给出某个时刻对应的速度 求出相邻时刻的平均速度 输出最大值 Sample Input23 // n2 2 //t v1 13 430 31 52 0 Sample OutputCase #1: 2.00Case #2: 5.00 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <string>