题解 宝可梦

传送门

发现它走的路径是一个环,于是就变成了计算环上两点间距离
当然细节有亿点多

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 500010
#define ll long long
//#define int long long

int n, m, q;
bool **mp;
char s[N], t1[10];

namespace force{
	const int dlt[][2]={{1,0},{0,1},{-1,0},{0,-1}};
	int calc(int x, int y, int c, int d, int t) {
		int tot=1, nxt, nxtx, nxty;
		if (x==c && y==d) return 0;
		x=x+dlt[t][0], y=y+dlt[t][1];
		while (1) {
			// cout<<"tot: "<<tot<<' '<<x<<' '<<y<<endl;
			if (x==c && y==d) return tot;
			++tot;
			nxt=((t-1)%4+4)%4;
			nxtx=x+dlt[nxt][0], nxty=y+dlt[nxt][1];
			if (!mp[nxtx][nxty]) x=nxtx, y=nxty, t=nxt;
			else {
				nxt=t;
				nxtx=x+dlt[nxt][0], nxty=y+dlt[nxt][1];
				while (mp[nxtx][nxty]) {
					nxt=(nxt+1)%4;
					nxtx=x+dlt[nxt][0], nxty=y+dlt[nxt][1];
				}
				x=nxtx, y=nxty, t=nxt;
			}
		}
	}
	void solve() {
		for (int i=1,a,b,c,d,dir; i<=q; ++i) {
			scanf("%d%d%d%d%s", &a, &b, &c, &d, t1);
			if (*t1=='U') dir=2;
			else if (*t1=='D') dir=0;
			else if (*t1=='L') dir=3;
			else dir=1;
			printf("%d\n", calc(a, b, c, d, dir));
		}
		exit(0);
	}
}

namespace task1{
	int vis[N][4];
	const int dlt[][2]={{1,0},{0,1},{-1,0},{0,-1}};
	inline int num(int i, int j) {return (i-1)*m+j;}
	void solve() {
		int x, y, u, t=0, nxtx, nxty, nxt, tot=0;
		int sx, sy;
		for (int j=1; j<=m; ++j) for (int i=1; i<=n; ++i) if (!mp[i][j]) {sx=x=i, sy=y=j; goto jump;}
		jump: ;
		memset(vis, -1, sizeof(vis));
		// cout<<"xy: "<<x<<' '<<y<<endl;
		while (vis[u=num(x, y)][t]==-1 || u!=num(sx, sy)) {
			vis[u][t]=tot++;
			// printf("vis[%d,%d][%d]=%d\n", x, y, t, tot-1);
			nxt=((t-1)%4+4)%4;
			nxtx=x+dlt[nxt][0], nxty=y+dlt[nxt][1];
			if (!mp[nxtx][nxty]) {
				// assert(vis[u][nxt]==-1);
				// if (vis[u][nxt]!=-1) cout<<"error: "<<x<<' '<<y<<' '<<nxt<<endl;
				if (vis[u][nxt]==-1) {
					// vis[u][nxt]=tot-1, printf("vis0[%d,%d][%d]=%d\n", x, y, nxt, tot-1);
				}
				x=nxtx, y=nxty, t=nxt;
				// cout<<"pos1"<<endl;
			}
			else {
				// cout<<"pos2"<<endl;
				nxt=t;
				nxtx=x+dlt[nxt][0], nxty=y+dlt[nxt][1];
				while (mp[nxtx][nxty]) {
					// if (nxt!=t && ~vis[u][nxt]) goto jump2;
					if (nxt!=t) {
						vis[u][nxt]=tot-1;
						// printf("vis1[%d,%d][%d]=%d\n", x, y, nxt, tot-1);
					}
					nxt=(nxt+1)%4;
					nxtx=x+dlt[nxt][0], nxty=y+dlt[nxt][1];
				}
				// cout<<"pos3"<<endl;
				if (nxt!=t) {
					if (vis[u][nxt]!=-1) {
						// cout<<"error: "<<x<<' '<<y<<' '<<nxt<<endl;
						break;
					}
					// if (nxt!=t && ~vis[u][nxt]) goto jump2;
					vis[u][nxt]=tot-1;
					// printf("vis2[%d,%d][%d]=%d\n", x, y, nxt, tot-1);
				}
				x=nxtx, y=nxty, t=nxt;
			}
			jump2: ;
		}
		--tot;
		// cout<<"tot: "<<tot<<endl;
		int ans;
		for (int i=1,a,b,c,d,dir; i<=q; ++i) {
			ans=INF;
			scanf("%d%d%d%d%s", &a, &b, &c, &d, t1);
			if (a==c&&b==d) {puts("0"); continue;}
			if (mp[a][b]||mp[c][d]) {puts("-1"); continue;}
			if (*t1=='U') dir=2;
			else if (*t1=='D') dir=0;
			else if (*t1=='L') dir=3;
			else dir=1;
			a=a+dlt[dir][0], b=b+dlt[dir][1];
			if (mp[a][b]) {puts("-1"); continue;}
			if (a==c&&b==d) {puts("1"); continue;}
			for (int j=0,u=num(a,b),v=num(c,d); j<4; ++j) {
				if (vis[v][j]!=-1) {
					// cout<<vis[u][dir]<<' '<<vis[v][j]<<endl;
					if (vis[v][j]>vis[u][dir]) ans=min(ans, vis[v][j]-vis[u][dir]);
					else ans=min(ans, tot+vis[v][j]-vis[u][dir]);
				}
			}
			printf("%d\n", ans+1);
		}
		exit(0);
	}
}

signed main()
{
	freopen("pokemon.in", "r", stdin);
	freopen("pokemon.out", "w", stdout);

	scanf("%d%d", &n, &m);
	mp=new bool*[n+2];
	for (int i=0; i<=n+1; ++i) {
		mp[i]=new bool[m+2];
		for (int j=0; j<=m+1; ++j) mp[i][j]=1;
	}
	for (int i=1; i<=n; ++i) {
		scanf("%s", s+1);
		for (int j=1; j<=m; ++j) mp[i][j]=(s[j]=='X');
	}
	scanf("%d", &q);
	if (n<=20 && m<=20 && q<=20) force::solve();
	else task1::solve();

	return 0;
}
posted @ 2021-10-31 10:19  Administrator-09  阅读(0)  评论(0编辑  收藏  举报