ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P6474 [NOI Online #2 入门组] 荆轲刺秦王 题解--zhengjun

2022-06-11 14:04:49  阅读:133  来源: 互联网

标签:zhengjun -- 题解 u1 u2 int flag continue 351


我一开始就打出来了,可是忘记一个很重要的剪枝,就是如果当前的步数已经超过答案的步数就不用搜了,还有就是每一个点的每一种状态都只能走到一次(其实就是走到一个点,之前使用了相同的魔法已经到过这个点)那么也不用搜下去了。

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,c1,c2,d;//如题
int sx,sy,tx,ty;//起点终点坐标
string s;//读入的数据
int a[351][351];
int flag[351][351];
bool v[351][351][16][16];//剪枝二
void add(int i,int j,int x){
	for(int k=-x+1;k<=x-1;k++){//差分使复杂度降为n^3
		if(k+i<1||k+i>n)continue;
		int p=x-1-(k<0?-k:k);//可以自己找规律
		if(j-p<1)a[k+i][0]+=1;
		else a[k+i][j-p]+=1;
		if(j+p+1>m);
		else a[k+i][j+p+1]-=1;
	}
}
struct zj{
	int x,y,u1,u2,t;//坐标,隐身使用次数,瞬移使用次数,已经过了多长时间
};
int ans1=0x3fffffff,ans2=0x3fffffff,ans=0x3fffffff;
int X[8]={0,0,1,-1,1,1,-1,-1};
int Y[8]={1,-1,0,0,1,-1,1,-1};
void bfs(){
	queue<zj> q;
	q.push((zj){sx,sy,0,0,0});
	v[sx][sy][0][0]=1;//起点已经过
	while(!q.empty()){
		zj x=q.front();
		q.pop();
		if(x.t>ans)continue;//剪枝一
		if(x.x==tx&&x.y==ty){
			if(x.t<ans){
				ans=x.t;
				ans1=x.u1;
				ans2=x.u2;
			}
			else{
				if(ans1+ans2>x.u1+x.u2){//魔法使用次数少
					ans=x.t;
					ans1=x.u1;
					ans2=x.u2;
				}
				else if(ans1+ans2==x.u1+x.u2&&ans1>x.u1){//魔法一样,隐身少
					ans=x.t;
					ans1=x.u1;
					ans2=x.u2;
				}
			}
			continue;
		}
		for(int i=0;i<8;i++){
			int xx=x.x+X[i],yy=x.y+Y[i];
			if(xx<1||xx>n||yy<1||yy>m)continue;//越界
			if(flag[xx][yy]==1)continue;//有士兵
			if(a[xx][yy]<=0&&v[xx][yy][x.u1][x.u2]==0){//不在士兵的观察范围内
				v[xx][yy][x.u1][x.u2]=1;//标记
				q.push((zj){xx,yy,x.u1,x.u2,x.t+1});
			}
			else if(x.u1+1<=c1&&v[xx][yy][x.u1+1][x.u2]==0){//在士兵的观察范围内,使用隐身
				v[xx][yy][x.u1+1][x.u2]=1;//标记
				q.push((zj){xx,yy,x.u1+1,x.u2,x.t+1});
			}
		}
		if(x.u2+1>c2)continue;//无法使用瞬移
		for(int i=0;i<4;i++){
			int xx=x.x+X[i]*d,yy=x.y+Y[i]*d;
			if(xx<1||xx>n||yy<1||yy>m)continue;
			if(flag[xx][yy]==1)continue;
			if(a[xx][yy]<=0&&v[xx][yy][x.u1][x.u2+1]==0){
				v[xx][yy][x.u1][x.u2+1]=1;
				q.push((zj){xx,yy,x.u1,x.u2+1,x.t+1});
			}
			else if(x.u1<c1&&v[xx][yy][x.u1+1][x.u2+1]==0){
				v[xx][yy][x.u1+1][x.u2+1]=1;
				q.push((zj){xx,yy,x.u1+1,x.u2+1,x.t+1});
			}
		}
	}
}
int main(){
	scanf("%d%d%d%d%d",&n,&m,&c1,&c2,&d);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>s;
			if(s=="S")flag[i][j]=-2,sx=i,sy=j;
			else if(s=="T")flag[i][j]=-1,tx=i,ty=j;
			else if(s==".");
			else{
				flag[i][j]=1;
				int x=s[0]-'0';
				for(int i=1;i<s.length();i++)x=x*10+s[i]-'0';//像个快读
				add(i,j,x);//差分
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			a[i][j]+=a[i][j-1];//注意差分要加回去
		}
	}
	bfs();
	if(ans==0x3fffffff)printf("-1");//无解
	else printf("%d %d %d",ans,ans1,ans2);//输出
	return 0;
}

谢谢--zhengjun

标签:zhengjun,--,题解,u1,u2,int,flag,continue,351
来源: https://www.cnblogs.com/A-zjzj/p/16365745.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有