zoukankan      html  css  js  c++  java
  • [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


    数据范围与提示

    对于所有数据,$1leqslant X,Yleqslant 500,0leqslant A,B,Cleqslant {10}^9,2leqslant Nleqslant {10}^5,(x_1,y_1) eq (x_N,y_N)$。


    题解

    $20\%$算法:

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

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

    期望得分:$20$分。

    实际得分:$20$分。

    $60\%$算法:

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

    记得结合上面的代码。

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

    期望得分:$60$分。

    实际得分:$60$分。

    $100\%$算法:

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

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

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

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

    时间复杂度:$Theta(n+XYlog 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++

  • 相关阅读:
    Accoridion折叠面板
    mui列表系列
    按照中文首字母排序查询表数据
    五分位算法
    springmvc添加拦截器
    springmvc添加定时任务
    通过后台解决跨域调用接口问题
    eclipse搭建ssm框架
    Java 将图片转成base64,传到前台展示
    用mysql存储过程代替递归查询
  • 原文地址:https://www.cnblogs.com/wzc521/p/11494272.html
Copyright © 2011-2022 走看看