【ybt】【基算 广搜 课过 例4】荆轲刺秦王

21 篇文章 0 订阅
本文主要介绍了一道编程题——荆轲刺秦王,通过使用宽度优先搜索(BFS)策略来解决。题目要求考虑两种技能:隐身和瞬移,在不同条件下找到从起点到终点的最短路径。代码中详细展示了如何实现BFS,并优化路径消耗的技能次数,寻找最优解。
摘要由CSDN通过智能技术生成

荆轲刺秦王

题目链接:荆轲刺秦王


题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解题思路

首先,我们要学会一项很重要的技能:cp(copy&paste)

然后,我们要开始分类讨论

  1. 两个技能都不用。
  2. 只用隐身。
  3. 只用瞬移。
  4. 两个技能都用。

这道题其实也就是码量大了亿点而已,思路不是很难。

code

#include<iostream>
#include<cstdio>
#include<cstring>
#define chen using
#define du namespace
#define xiu std
chen du xiu;

const int xn[9]={0,0,1,0,-1,-1,1,-1,1};
const int yn[9]={0,1,0,-1,0,-1,1,1,-1};

int n,m,c1,c2,d,ex,ey;
int ans=0x3f3f3f3f,p,q,flg;
int a[400][400];
int b[400][400];
int v[400][400][20][20];

struct abc{
	int x,y,c1,c2,s;
}f[10000000];

int abs(int t)
{
	if(t<0)
		return -t;
	return t;
}

bool bfs()
{
	int hd=0,tl=1;
	v[f[hd].x][f[hd].y][0][0]=1;
	while(hd<tl)
	{
		hd++;
		hd%=10000000;
		for(int i=1;i<=8;i++)
		{
			int x=f[hd].x+xn[i];
			int y=f[hd].y+yn[i];
			if(x<1||x>n||y<1||y>m)
				continue;
			if(a[x][y]==0&&b[x][y]==0&&v[x][y][f[hd].c1][f[hd].c2]==0)
			{
				tl++;
				tl%=10000000;
				f[tl]=(abc){x,y,f[hd].c1,f[hd].c2,f[hd].s+1};
				v[x][y][f[hd].c1][f[hd].c2]=1;
				if(x==ex&&y==ey)
				{
					v[x][y][f[hd].c1][f[hd].c2]=0;
					flg=1;
					if(f[tl].s<ans)
					{
						ans=f[tl].s;
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2<p+q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2==p+q&&f[tl].c2<q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
				}
			}
			if(b[x][y]==1&&a[x][y]==0&&v[x][y][f[hd].c1+1][f[hd].c2]==0&&f[hd].c1+1<=c1)
			{
				tl++;
				tl%=10000000;
				f[tl]=(abc){x,y,f[hd].c1+1,f[hd].c2,f[hd].s+1};
				v[x][y][f[hd].c1+1][f[hd].c2]=1;
				if(x==ex&&y==ey)
				{
					v[x][y][f[hd].c1+1][f[hd].c2]=0;
					flg=1;
					if(f[tl].s<ans)
					{
						ans=f[tl].s;
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2<p+q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2==p+q&&f[tl].c2<q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
				}
			}
			if(i>4)
				continue;
			x=f[hd].x+d*xn[i];
			y=f[hd].y+d*yn[i];
			if(x<1||x>n||y<1||y>m)
				continue;
			if(b[x][y]==0&&a[x][y]==0&&v[x][y][f[hd].c1][f[hd].c2+1]==0&&f[hd].c2+1<=c2)
			{
				tl++;
				tl%=10000000;
				f[tl]=(abc){x,y,f[hd].c1,f[hd].c2+1,f[hd].s+1};
				v[x][y][f[hd].c1][f[hd].c2+1]=1;
				if(x==ex&&y==ey)
				{
					v[x][y][f[hd].c1][f[hd].c2+1]=0;
					flg=1;
					if(f[tl].s<ans)
					{
						ans=f[tl].s;
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2<p+q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2==p+q&&f[tl].c2<q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
				}
			}
			if(b[x][y]==1&&a[x][y]==0&&v[x][y][f[hd].c1+1][f[hd].c2+1]==0&&f[hd].c1+1<=c1&&f[hd].c2+1<=c2)
			{
				tl++;
				tl%=10000000;
				f[tl]=(abc){x,y,f[hd].c1+1,f[hd].c2+1,f[hd].s+1};
				v[x][y][f[hd].c1+1][f[hd].c2+1]=1;
				if(x==ex&&y==ey)
				{
					v[x][y][f[hd].c1+1][f[hd].c2+1]=0;
					flg=1;
					if(f[tl].s<ans)
					{
						ans=f[tl].s;
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2<p+q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
					if(f[tl].s==ans&&f[tl].c1+f[tl].c2==p+q&&f[tl].c2<q)
					{
						p=f[tl].c1;
						q=f[tl].c2;
					}
				}
			}
		}
	}
}

int main()
{
	cin>>n>>m>>c1>>c2>>d;
	char c;
	c=getchar();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			c=getchar();
			while(c!=' '&&c!='\n')
			{
				a[i][j]=a[i][j]*10+c-'0';
				c=getchar();
			}
			if(a[i][j]=='S'-48)
				f[1].x=i,f[1].y=j,a[i][j]=0;
			if(a[i][j]=='T'-48)
				ex=i,ey=j,a[i][j]=0;
			if(a[i][j]=='.'-48)
				a[i][j]=0;
			if(a[i][j]<=15&&a[i][j]>=1)
			{
				for(int ii=max(1,i-a[i][j]);ii<=min(n,i+a[i][j]);ii++)
					for(int jj=max(1,j-a[i][j]);jj<=min(m,j+a[i][j]);jj++)
						if(abs(i-ii)+abs(j-jj)<a[i][j]&&a[ii][jj]==0)
							b[ii][jj]=1;
			}
		}
	bfs();
	if(!flg)
		cout<<-1<<endl;
	else
		printf("%d %d %d\n",ans,p,q);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值