Luogu interesting question [Pawn crossing the river] reference question solution

background

I just noticed this question when I was visiting Luogu today. The original question is connected to [P1002 [NOIP2002 Popularization Group] Crossing the River - Luogu | New Ecology of Computer Science Education (luogu. com.cn)

For me, who loves to play chess, it is of course a must-do question.

Question meaning

The starting point of the pawn is at the upper left corner (0,0), and our program will receive two coordinates: the lower right corner of the pawn's target point (end_x, end_y), and the coordinate point of the enemy horse (horse_x, horse_y).

Among them, the pawn can only move one square to the right or down, and cannot pass through the knight's feet and position, and up to nine points cannot be passed.

Find how many solutions there are from the upper left corner to the lower right corner. The agreed maximum coordinate value of the data volume shall not exceed 20.

parse

At first glance, we all know that this should be a recursive algorithm examination question, in which the solution formula for the number of solutions for the target point should be

res(end_x,end_y)=res(end_x-1,end_y)+res(end_x,end_y-1)

where res(0,0)=1

We start from (0,0) and use the first-in-first-out data structure of the queue to effectively solve this problem.

Since a point may arrive due to two points, in order to remove duplicates, we need to use a flag array flag and double queues so that each point will only be queued at most once.

Taking into account the existence of enemy horses, we add negative values ​​to the horse's feet and horse positions. Every time we pass these negative value positions, we will not join the team. Otherwise, we will join the team and mark this position. The next time we search for this position, we will only add The number of plans does not continue to join the team.

When the queue is completely empty, the result comes out, which is res(end_x,end_y)

Time complexity O(n^2), space complexity O(n^2)

code

#include<bits/stdc++.h>
using namespace std;

class point {
	public:
		int x,y;
};

int main() {
	int start_x=0,start_y=0;
	int horse_x,horse_y;
	int end_x,end_y;
	cin>>end_x>>end_y>>horse_x>>horse_y;

	long long res[21][21]= {0};
	res[0][0]=1;
	bool flag[21][21]= {0};

	int horse_direct[][2]= {
		{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}
	};
	res[horse_x][horse_y]=-1;
	for(int k=0; k<8; k++) {
		int x=horse_x+horse_direct[k][0];
		int y=horse_y+horse_direct[k][1];
		if(x>=0&&y>=0&&x<=end_x&&y<=end_y) {
			res[x][y]=-1;
		}
	}

	int soldier_direct[][2]= {
   
   {0,1},{1,0}};

	queue<point> q;
	q.push({start_x,start_y});

	while(!q.empty()) {
		queue<point> nq;
		memset(flag,0,sizeof(flag));
		while(!q.empty()) {
			point p=q.front();
			q.pop();

			for(int k=0; k<2; k++) {
				int x=p.x+soldier_direct[k][0];
				int y=p.y+soldier_direct[k][1];

				if(x<0||y<0||x>end_x||y>end_y) {
					continue;
				}
				if(res[x][y]<0) {
					continue;
				}

				res[x][y]+=res[p.x][p.y];
				if(!flag[x][y]) {
					nq.push({x,y});
					flag[x][y]=1;
				}
			}
		}
		q=nq;
	}
	
	cout<<res[end_x][end_y]<<endl;

	return 0;
}

submit

Guess you like

Origin blog.csdn.net/qq_36694133/article/details/134108517