[CSP-S模拟测试]:游戏(最短路)

题目传送门(内部题35)


输入格式

第一行,两个正整数$X,Y$。
第二行,三个非负整数$A,B,C$。
第三行,一个正整数$N$。
接下来$N$行,每行两个非负整数$x_i,y_i$。


输出格式

一行,一个非负整数表示答案。


样例

样例输入1:

6 5
1 3 6
3
1 1
0 4
6 5

样例输出1:

26

样例输入2:

3 3
0 50 10
2
0 0
3 3

样例输出2:

60

样例输入3:

4 6
0 5 1000
6
3 1
4 6
3 0
3 0
4 0
0 4

样例输出3:

2020


数据范围与提示

对于所有数据,$1\leqslant X,Y\leqslant 500,0\leqslant A,B,C\leqslant {10}^9,2\leqslant N\leqslant {10}^5,(x_1,y_1)\neq (x_N,y_N)$。


题解

$20\%$算法:

一堆$if,else$,打对$20$分就到手了。

时间复杂度:$\Theta(1)$。

期望得分:$20$分。

实际得分:$20$分。

$60\%$算法:

发现$A=0$,所以我们可以将所有的莉露露连边,然后跑对短路就好了。

记得结合上面的代码。

时间复杂度:$\Theta(N^2\log N^2)$。

期望得分:$60$分。

实际得分:$60$分。

$100\%$算法:

发现肯定是最近的莉露露过来,所以我们可以多源点$BFS$预处理出来每个点最近的莉露露。

然后对于移动的操作,显然我们不能将一条路径上每对点都连边,所以我们可以只和临近的四个点连边即可。

对于抛的操作,分为横着抛和竖着抛,然后将最近的莉露露连过来即可。

注意需要建三张图,因为抛的操作不能中途转向(我也是调了好久才发现……),可以不建边跑最短路。

时间复杂度:$\Theta(n+XY\log XY)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

$20\%$算法:

#include<bits/stdc++.h>
using namespace std;
long long X,Y,N;
long long A,B,C;
pair<long long,long long> pos[100001];
int main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&X,&Y,&A,&B,&C,&N);
	for(long long i=1;i<=N;i++)
	{
		long long x,y;
		scanf("%lld%lld",&x,&y);
		pos[i]=make_pair(x,y);
	}
	long long ans=0;
	bool flag1=0,flag2=0;
	long long deltax=abs(pos[1].first-pos[2].first);
	long long deltay=abs(pos[1].second-pos[2].second);
	if(C*deltax<A*deltax+B){ans+=C*deltax;flag1=1;}
	if(C*deltay<A*deltay+B){ans+=C*deltay;flag2=1;}
	if(flag1&&flag2){printf("%lld",ans);return 0;}
	if(flag1){printf("%lld",ans+A*deltay+B);return 0;}
	if(flag2){printf("%lld",ans+A*deltax+B);return 0;}
	printf("%lld",min(C*deltax+A*deltay+B,C*deltay+A*deltax+B));
	return 0;
}

$60\%$算法:

#include<bits/stdc++.h>
using namespace std;
struct rec
{
	long long nxt,to,w;
}e[2000010];
long long head[1010],cnt;
long long X,Y,N;
long long A,B,C;
long long dis[1010];
pair<long long,long long> pos[100001];
priority_queue<pair<long long,long long>,vector<pair<long long,long long> >,greater<pair<long long,long long> > >q;
bool vis[1010];
void add(long long x,long long y,long long w)
{
	e[++cnt].nxt=head[x];
	e[cnt].to=y;
	e[cnt].w=w;
	head[x]=cnt;
}
void Dij()
{
	for(long long i=2;i<=N;i++)dis[i]=200209230020020923;
	q.push(make_pair(0,1));
	while(!q.empty())
	{
		long long flag=q.top().second;
		q.pop();
		if(vis[flag])continue;
		vis[flag]=1;
		for(long long i=head[flag];i;i=e[i].nxt)
			if(dis[e[i].to]>dis[flag]+e[i].w)
			{
				dis[e[i].to]=dis[flag]+e[i].w;
				q.push(make_pair(dis[e[i].to],e[i].to));
			}
	}
}
int main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&X,&Y,&A,&B,&C,&N);
	for(long long i=1;i<=N;i++)
	{
		long long x,y;
		scanf("%lld%lld",&x,&y);
		pos[i]=make_pair(x,y);
	}
	if(N<=1000&&!A)
	{
		for(long long i=1;i<=N;i++)
			for(long long j=i+1;j<=N;j++)
			{
				long long ans=0;
				bool flag1=0,flag2=0;
				long long deltax=abs(pos[i].first-pos[j].first);
				long long deltay=abs(pos[i].second-pos[j].second);
				if(C*deltax<A*deltax+B){ans+=C*deltax;flag1=1;}
				if(C*deltay<A*deltay+B){ans+=C*deltay;flag2=1;}
				if(flag1&&flag2){add(i,j,ans);add(j,i,ans);continue;}
				if(flag1){add(i,j,ans+A*deltay+B);add(j,i,ans+A*deltay+B);continue;}
				if(flag2){add(i,j,ans+A*deltax+B);add(j,i,ans+A*deltax+B);continue;}
				add(i,j,min(C*deltax+A*deltay+B,C*deltay+A*deltax+B));
				add(j,i,min(C*deltax+A*deltay+B,C*deltay+A*deltax+B));
			}
		Dij();
		cout<<dis[N]<<endl;
		return 0;
	}
	long long ans=0;
	bool flag1=0,flag2=0;
	long long deltax=abs(pos[1].first-pos[2].first);
	long long deltay=abs(pos[1].second-pos[2].second);
	if(C*deltax<A*deltax+B){ans+=C*deltax;flag1=1;}
	if(C*deltay<A*deltay+B){ans+=C*deltay;flag2=1;}
	if(flag1&&flag2){printf("%lld",ans);return 0;}
	if(flag1){printf("%lld",ans+A*deltay+B);return 0;}
	if(flag2){printf("%lld",ans+A*deltax+B);return 0;}
	printf("%lld",min(C*deltax+A*deltay+B,C*deltay+A*deltax+B));
	return 0;
}

$100\%$算法:

#include<bits/stdc++.h>
using namespace std;
struct node{long long x,y;};
struct rec
{
	long long x,y,w;
	long long val;
};
long long X,Y,N;
long long A,B,C;
long long Map[600][600];
long long dis[600][600][3];
bool vis[600][600][3];
pair<long long,long long> pos[1000001];
queue<node> q;
priority_queue<rec> dij;
bool operator<(rec a,rec b){return a.val>b.val;}
void pre_work()
{
	memset(dis,0x15f,sizeof(dis));
	memset(Map,-1,sizeof(Map));
}
void BFS()
{
	while(q.size())
	{
		long long x=q.front().x;
		long long y=q.front().y;
		q.pop();
		if(x<X&&Map[x+1][y]==-1)
		{
			Map[x+1][y]=Map[x][y]+1;
			q.push((node){x+1,y});
		}
		if(x&&Map[x-1][y]==-1)
		{
			Map[x-1][y]=Map[x][y]+1;
			q.push((node){x-1,y});
		}
		if(y<Y&&Map[x][y+1]==-1)
		{
			Map[x][y+1]=Map[x][y]+1;
			q.push((node){x,y+1});
		}
		if(y&&Map[x][y-1]==-1)
		{
			Map[x][y-1]=Map[x][y]+1;
			q.push((node){x,y-1});
		}
	}
}
void Dij()
{
	dis[pos[1].first][pos[1].second][0]=0;
	dij.push((rec){pos[1].first,pos[1].second,0,0});
	while(!dij.empty())
	{
		long long x=dij.top().x;
		long long y=dij.top().y;
		long long w=dij.top().w;
		dij.pop();
		if(x==pos[N].first&&y==pos[N].second&&!w)break;
		if(vis[x][y][w])continue;
		vis[x][y][w]=1;
		switch(w)
		{
			case 0:
			if(x&&dis[x][y][0]+C<dis[x-1][y][0])
			{
				dis[x-1][y][0]=dis[x][y][0]+C;
				dij.push((rec){x-1,y,0,dis[x-1][y][0]});
			}
			if(x<X&&dis[x][y][0]+C<dis[x+1][y][0])
			{
				dis[x+1][y][0]=dis[x][y][0]+C;
				dij.push((rec){x+1,y,0,dis[x+1][y][0]});
			}
			if(y&&dis[x][y][0]+C<dis[x][y-1][0])
			{
				dis[x][y-1][0]=dis[x][y][0]+C;
				dij.push((rec){x,y-1,0,dis[x][y-1][0]});
			}
			if(y<Y&&dis[x][y][0]+C<dis[x][y+1][0])
			{
				dis[x][y+1][0]=dis[x][y][0]+C;
				dij.push((rec){x,y+1,0,dis[x][y+1][0]});
			}
			if(dis[x][y][0]+Map[x][y]*C<dis[x][y][1])
			{
				dis[x][y][1]=dis[x][y][0]+Map[x][y]*C;
				dij.push((rec){x,y,1,dis[x][y][1]});
			}
			if(dis[x][y][0]+Map[x][y]*C<dis[x][y][2])
			{
				dis[x][y][2]=dis[x][y][0]+Map[x][y]*C;
				dij.push((rec){x,y,2,dis[x][y][2]});
			}
			break;
			case 1:
			if(x<X&&dis[x][y][1]+A<dis[x+1][y][1])
			{
				dis[x+1][y][1]=dis[x][y][1]+A;
				dij.push((rec){x+1,y,1,dis[x+1][y][1]});
			}
			if(x&&dis[x][y][1]+A<dis[x-1][y][1])
			{
				dis[x-1][y][1]=dis[x][y][1]+A;
				dij.push((rec){x-1,y,1,dis[x-1][y][1]});
			}
			if(dis[x][y][1]+B<dis[x][y][0])
			{
				dis[x][y][0]=dis[x][y][1]+B;
				dij.push((rec){x,y,0,dis[x][y][0]});
			}
			break;
			case 2:
			if(y<Y&&dis[x][y][2]+A<dis[x][y+1][2])
			{
				dis[x][y+1][2]=dis[x][y][2]+A;
				dij.push((rec){x,y+1,2,dis[x][y+1][2]});
			}
			if(y&&dis[x][y][2]+A<dis[x][y-1][2])
			{
				dis[x][y-1][2]=dis[x][y][2]+A;
				dij.push((rec){x,y-1,2,dis[x][y-1][2]});
			}
			if(dis[x][y][2]+B<dis[x][y][0])
			{
				dis[x][y][0]=dis[x][y][2]+B;
				dij.push((rec){x,y,0,dis[x][y][0]});
			}
			break;
		}
	}
}
int main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&X,&Y,&A,&B,&C,&N);
	pre_work();
	for(long long i=1;i<=N;i++)
	{
		long long x,y;
		scanf("%lld%lld",&x,&y);
		pos[i]=make_pair(x,y);
		q.push((node){x,y});
		Map[x][y]=0;
	}
	BFS();
	Dij();
	printf("%lld",dis[pos[N].first][pos[N].second][0]);
	return 0;
}

rp++

posted @ 2019-09-09 21:07  HEOI-动动  阅读(225)  评论(0编辑  收藏  举报