ABC384E题通过历程

原题连接:[ABC384E]

在赛时的时候,我们写出了一份非常牛逼的代码:

# include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 510;
int a[N][N];
int vis[N][N];
struct node {
    bool operator()(int a, int b) 
	{
        return a > b;
    }
};
int dx[] = {0,1,-1,0};
int dy[] = {1,0,0,-1};
priority_queue<int,vector<int>,node> q;
signed main (){
	int h,w,x;
	scanf("%lld%lld%lld",&h,&w,&x);
	int p,y;
	scanf("%lld%lld",&p,&y);
	for(int i = 1;i <= h;i++)
	{
		for(int j = 1;j <= w;j++)
		{
			scanf("%lld",&a[i][j]);
		}
	}
//	q.push(1);
//	q.push(2);
//	cout << q.top() << endl;
	int res = a[p][y];
	vis[p][y] = 1;
//	q.push(res);
	queue<pair<int,int> > bfs;
	bfs.push({p,y});
	while(!bfs.empty())
	{
		int nowx = bfs.front().first;
		int nowy = bfs.front().second;
		bfs.pop();
		for(int i = 0;i < 4;i++)
		{
			int now2x = nowx+dx[i];
			int now2y = nowy+dy[i];
			if(now2x < 1 || now2x > h || now2y < 1 || now2y > w || vis[now2x][now2y] == 1) continue;
			else
			{
				q.push(a[now2x][now2y]);
			}
		}
//		cout << res << endl;
		while(true && !q.empty())
		{
			if(q.top()*x < res)
			{
				res += q.top();
				for(int i = 0;i < 4;i++)
				{
					int now2x = nowx+dx[i];
					int now2y = nowy+dy[i];
					if(a[now2x][now2y] == q.top())
					{
//						cout << now2x << " " << now2y << endl;
						bfs.push({now2x,now2y});
						vis[now2x][now2y] = 1;
					}
				}
				q.pop();
			}
			else break;
		}
	}
	cout << res << endl;
	return 0;
} 

如果你仔细研究这个题目,就会发现这个代码存在manymany的错误,首先是在下面查找位置的时候没有判断边界,况且这个判断方式也不够正确,对于一个位置周边存在多个相同且满足a[now2x][now2y] == q.top()时,哪一个时我们的来时路呢?所以,我们积累经验,在传入优先队列的时候就把这个点的位置存进去,也就是这么钦定优先队列:

typedef pair<int, int> PII;
typedef pair<int, PII> PLI;
priority_queue<PLI, vector<PLI>, greater<PLI> > q;

然后传入的时候这么写:

q.push({a[now2x][now2y],{now2x,now2y}});

同时啊,我们考虑对于打标记这里,在实现方面,我们发现优先队列有可能不是清空的,后面有可能还要用到,那么不如直接就在传入队列的时候就打上标记,然后后面直接用就好了,也就是这样:

          for(int i = 0;i < 4;i++)
          { 
			int now2x = nowx+dx[i];
			int now2y = nowy+dy[i];
//			if(now2x == 2 && now2y == 4)
//				cout << now2x << " " << now2y << endl;
			if(now2x < 1 || now2x > h || now2y < 1 || now2y > w || vis[now2x][now2y]) continue;
			else
			{
				q.push({a[now2x][now2y],{now2x,now2y}});
      			vis[now2x][now2y]++;
			}
		}
//		cout << res << endl;
		while(!q.empty())
		{
			if(q.top().first*x < res)
			{
				res += q.top().first;
				int now2x = q.top().second.first;
				int now2y = q.top().second.second;
				bfs.push({now2x,now2y});
				q.pop();				 
			}
			else break;
		}

最后,我们为了避免精度误差,所以采用了\(*x\)的做法,要注意到这个题目的\(s_{i,j} \times x\)会达到\(10^{21}\),所以,记得__int128!!!!,那么我们就得到了完整的AC代码:

code

向lzq学长致谢!!!
百年奋斗史:

posted @ 2024-12-16 23:43  Lunar_Whisper  阅读(1)  评论(0编辑  收藏  举报