G.Snake Move

  • 赛后独立思考了不算长的一段时间,然后就通过了;赛时没看这道题有些可惜,算是个教训吧
  • 发现两个性质之后,这道题就非常简单了:
    1.只有初始位置的贪吃蛇才可能会对最优路径产生影响
    2.令贪吃蛇长度-1的操作等价于它停在原地不动
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int a[3005][3005];
int f[3005][3005];
int read1()
{
	char cc=getchar();
	while(!(cc>=48&&cc<=57))
	{
		if(cc=='-')
		{
			break;
		}
		cc=getchar();
	}
	bool f=false;
	int s=0;
	if(cc=='-')
	{
		f=true;
	}
	else
	{
		s=cc-48;
	}
	while(1)
	{
		cc=getchar();
		if(cc>=48&&cc<=57)
		{
			s=s*10+cc-48;
		}
		else
		{
			break;
		}
	}
	if(f==true)
	{
		s=-s;
	}
	return s;
}
struct t1
{
	int x,y,w;
};
bool operator <(t1 a,t1 b)
{
	if(a.w!=b.w)
	{
		return a.w<b.w;
	}
	else if(a.x!=b.x)
	{
		return a.x<b.x;
	}
	return a.y<b.y;
}
priority_queue<t1>q;
deque<pair<int,int> >q1;
deque<int>q2;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
void bfs(int s,int t)
{
	f[s][t]=0;
	q1.push_back(make_pair(s,t));
	q2.push_back(0);
	while(!(q1.empty()&&q.empty()))
	{
		if(q1.empty()||!q.empty()&&-q.top().w<=q2.front())
		{
			t1 tmp=q.top();
			q.pop();
			q1.push_front(make_pair(tmp.x,tmp.y));
			q2.push_front(-tmp.w);
		}
		int x=q1.front().first,y=q1.front().second;
		q1.pop_front();
		int w=q2.front();
		q2.pop_front();
		for(int i=0;i<4;i++)
		{
			if(w>=a[x+dx[i]][y+dy[i]]&&w+1<f[x+dx[i]][y+dy[i]])
			{
				f[x+dx[i]][y+dy[i]]=w+1;
				q1.push_back(make_pair(x+dx[i],y+dy[i]));
				q2.push_back(w+1);
			}
			else if(a[x+dx[i]][y+dy[i]]!=INT_MAX&&w+1<f[x+dx[i]][y+dy[i]])
			{
				t1 tmp;
				tmp.x=x;tmp.y=y;tmp.w=-a[x+dx[i]][y+dy[i]];
				q.push(tmp);
			}
		}
	}
}
int main()
{
	int n,m,k;
	cin>>n>>m>>k;
	int s,t;
	for(int i=1;i<=k;i++)
	{
		int x,y;
		x=read1();
		y=read1();
		if(i==1)
		{
			s=x;
			t=y;
		}
		a[x][y]=k-i;
	}
	string S;
	for(int i=1;i<=n;i++)
	{
		cin>>S;
		for(int j=1;j<=m;j++)
		{
			if(a[i][j]==0)
			{
				if(S[j-1]=='.')
				{
					a[i][j]=0;
				}
				else
				{
					a[i][j]=INT_MAX;
				}
			}
			a[0][j]=a[n+1][j]=INT_MAX;
		}
		a[i][0]=a[i][m+1]=INT_MAX;
	}
	memset(f,0x3f,sizeof(f));
	bfs(s,t);
	unsigned long long ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			long long tmp=f[i][j];
			if(f[i][j]<1000000000)
			{
				ans=ans+tmp*tmp;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2024-01-24 19:35  D06  阅读(230)  评论(0编辑  收藏  举报