1. 程式人生 > 實用技巧 >ES 實現聚合分頁

ES 實現聚合分頁

CF1063B Labyrinth

洛谷傳送門

題目描述

You are playing some computer game. One of its levels puts you in a maze consisting of nn lines, each of which contains mm cells. Each cell either is free or is occupied by an obstacle. The starting cell is in the row rr and column cc . In one step you can move one square up, left, down or right, if the target cell is not occupied by an obstacle. You can't move beyond the boundaries of the labyrinth.

Unfortunately, your keyboard is about to break, so you can move left no more than xx times and move right no more than yy times. There are no restrictions on the number of moves up and down since the keys used to move up and down are in perfect condition.

Now you would like to determine for each cell whether there exists a sequence of moves that will put you from the starting cell to this particular one. How many cells of the board have this property?

輸入格式

The first line contains two integers nn , mm ( 1<=n,m<=20001<=n,m<=2000 ) — the number of rows and the number columns in the labyrinth respectively.

The second line contains two integers rr , cc ( 1<=r<=n1<=r<=n , 1<=c<=m1<=c<=m ) — index of the row and index of the column that define the starting cell.

The third line contains two integers xx , yy ( 0<=x,y<=10^{9}0<=x,y<=109 ) — the maximum allowed number of movements to the left and to the right respectively.

The next nn lines describe the labyrinth. Each of them has length of mm and consists only of symbols '.' and ''. The jj* -th character of the ii -th line corresponds to the cell of labyrinth at row ii and column jj . Symbol '.' denotes the free cell, while symbol '*' denotes the cell with an obstacle.

It is guaranteed, that the starting cell contains no obstacles.

輸出格式

Print exactly one integer — the number of cells in the labyrinth, which are reachable from starting cell, including the starting cell itself.

題意翻譯

題意描述

你正在玩一款電腦遊戲。在其中一關,你位於一個 nn 行 mm 列的迷宮。每個格子要麼是可以通過的空地,要麼是障礙。迷宮的起點位於第 rr 行第 cc 列。你每一步可以向上、下、左、右中的一個方向移動一格,前提是那一格不是障礙。你無法越出迷宮的邊界。

不幸的是,你的鍵盤快壞了,所以你只能向左移動不超過 xx 格,並且向右移動不超過 yy 格。因為上下鍵情況良好,所以對向上和向下的移動次數沒有限制。

現在你想知道在滿足上述條件的情況下,從起點出發,有多少格子可以到達(包括起點)?

輸入輸出格式

輸入格式:

第一行包含兩個數 n, mn,m (1 <= n, m, <= 2000)(1<=n,m,<=2000) ,表示迷宮的行數和列數。

第二行包含兩個數 r,cr,c (1 <= r <= n, 1 <= c <= m)(1<=r<=n,1<=c<=m) ,表示起點位於第 rr 行第 cc 列。

第三行包含兩個數 x,yx,y (1 <= x,y <= 10^9)(1<=x,y<=109) ,表示最多向左或向右移動的次數。

接下來 nn 行描述這個迷宮,每行為一個長為 mm 的由 '.' 和 '' 組成的字串。 '.' 表示空地, '' 表示障礙。 輸入保證起點不是障礙。

輸出格式:

輸出一個整數,表示從起點出發可以到達的格子數,包括起點本身。

說明/提示

Cells, reachable in the corresponding example, are marked with '+'.

First example:

+++..
+***.
+++**
*+++.

Second example:

.++.
.+*.
.++.
.++.

題解:

一開始的思路是加限制的深搜。只維護了左右步數作為剪枝。還沒挺到第40號點就掛了。

就不放程式碼了吧。

問題出在哪了呢?

可以發現的是,對於一組起終點,它可以有多種路徑到達。但是這些種類的路徑可能會導致它繞道走好多,導致它先被劣方案走到,然後不能被更好的方案更新。這個點就卡死在這裡了。

要考慮避免這種情況出現。就需要記錄每個點的最優距離和。

程式碼:

#include<cstdio>
using namespace std;
const int maxn=2010;
int n,m,r,c,lx,ly,head,tail,cnt;
char mp[maxn][maxn];
int sum[maxn][maxn];
int dx[]={-1,1,0,0};
int dy[]={0,0,1,-1};
struct node
{
	int xx;
	int yy;
	int cl;
	int cr;
}q[maxn*maxn];
int main()
{ 
	char cc;
	scanf("%d%d%d%d%d%d",&n,&m,&r,&c,&lx,&ly);
	for(int i=1;i<=n;i++)
	{
		scanf("%c",&cc);
		for(int j=1;j<=m;j++)
			scanf("%c",&mp[i][j]);
	}
	tail++;
	q[tail].xx=r;
	q[tail].yy=c;
	q[tail].cl=lx;
	q[tail].cr=ly;
	sum[r][c]=lx+ly;
	cnt++;
	while(head!=tail)
	{
		head++;
		for(int px,py,i=0;i<4;i++)
		{
			px=q[head].xx+dx[i];
			py=q[head].yy+dy[i];
			if(px>0&&py>0&&px<=n&&py<=m&&mp[px][py]!='*')
				if(mp[px][py]!='+')
				{
					if(i==2)
					{
						if(q[head].cr>0)
						{
							tail++;
							q[tail].xx=px;
							q[tail].yy=py;
							q[tail].cr=q[head].cr-1;
							q[tail].cl=q[head].cl;
							mp[px][py]='+';
							sum[px][py]=q[tail].cl+q[tail].cr;
							cnt++;
						}
						continue;
					}
					if(i==3)
					{
						if(q[head].cl>0)
						{
							tail++;
							q[tail].xx=px;
							q[tail].yy=py;
							q[tail].cr=q[head].cr;
							q[tail].cl=q[head].cl-1;
							mp[px][py]='+';
							sum[px][py]=q[tail].cl+q[tail].cr;
							cnt++;
						}
						continue;
					}
					tail++;
					q[tail].xx=px;
					q[tail].yy=py;
					q[tail].cr=q[head].cr;
					q[tail].cl=q[head].cl;
					mp[px][py]='+';
					sum[px][py]=q[tail].cl+q[tail].cr;
					cnt++;
				}
				else 
					if(sum[px][py]<q[head].cl+q[head].cr)
					{
						if(i==2)
						{
							if(q[head].cr>0&&sum[px][py]<q[head].cl+q[head].cr-1)
							{
								tail++;
								q[tail].xx=px;
								q[tail].yy=py;
								q[tail].cr=q[head].cr-1;
								q[tail].cl=q[head].cl;
								sum[px][py]=q[tail].cl+q[tail].cr;
							}
							continue;
						}
						if(i==3)
						{
							if(q[head].cl>0&&sum[px][py]<q[head].cl+q[head].cr-1)
							{
								tail++;
								q[tail].xx=px;
								q[tail].yy=py;
								q[tail].cr=q[head].cr;
								q[tail].cl=q[head].cl-1;
								sum[px][py]=q[tail].cl+q[tail].cr;
							}
							continue;
						}       
						tail++;
						q[tail].xx=px;
						q[tail].yy=py;
						q[tail].cr=q[head].cr;
						q[tail].cl=q[head].cl;
						sum[px][py]=q[tail].cl+q[tail].cr;
					}
		}
	}
	printf("%d",cnt);
	return 0;
}