计蒜客 蓝桥杯

1.迷宫
有一个n×m 的迷宫,其中 . 表示空地, * 表示障碍物。除此之外,有 qq 个单向传送门:如果进入格子 (a_i,b_i)那么会被立即传送到 (c_i,d_i)保证每个点至多是一个传送门的入口。如果传送门最终传送到障碍物上,那么将会卡在障碍物上不能移动在传送门内部传送的花费是 0,在空地上每次可以往周围四个格子移动,花费是 1。现在我们想知道从 (1,1)走到 (x,y) 的最短距离。如果无法到达终点,输出 “No solution”。只要经过终点就算到达,即如果终点上有传送门也没有关系。
只过了一半数据

#include<bits/stdc++.h>
using namespace std;
int n,m,qq;
char a[1007][1007];
bool vis[1007][1007];
struct node{
	int x1,y1;
	int x2,y2;
}b[1007],c[1007];
struct node1{
	int x,y;
	int s;
};
int ex,ey;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int bfs(){
	queue<node1>q;
	node1 now,next,next1;
	now.x=0;now.y=0;now.s=0;
	q.push(now);
	memset(vis,0,sizeof(vis));
	vis[0][0]=1;
	while(!q.empty()){
		now=q.front();q.pop();
		for(int i=0;i<4;i++){
			int nx=now.x+dx[i];
			int ny=now.y+dy[i];
			int j;
			if(0<=nx&&nx<n&&0<=ny&&ny<m&&a[nx][ny]=='.'&&!vis[nx][ny]){
			        vis[nx][ny]=1;
                	next.x=nx,next.y=ny,next.s=now.s+1;
                	if(nx==ex&&ny==ey) return next.s;
                	int flag=0;
                	for(int j=0;j<qq;j++){
					if(nx==b[j].x1&&ny==b[j].y1) {
						flag=1;
						if(!vis[b[j].x2][b[j].y2]){
							vis[b[j].x2][b[j].y2]=1;
	                		next1.x=b[j].x2,next1.y=b[j].y2,next1.s=now.s+1;
	                		if(a[next1.x][next1.y]=='*') return -1;
	                		else if(next1.x==ex&&next1.y==ey) return next.s;
	                		else q.push(next1);
	                		break;
						}
						}
					}
					if(!flag) q.push(next);	
			}
		}
	}
	return -1;
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			cin>>a[i][j];
		}
	}
	cin>>qq;
	for(int i=0;i<qq;i++){
		cin>>b[i].x1>>b[i].y1>>b[i].x2>>b[i].y2;
		b[i].x1-=1;b[i].x2-=1;b[i].y1-=1;b[i].y2-=1;
	}
	cin>>ex>>ey;
	ex=ex-1;
	ey=ey-1;
	int ans=bfs();
	if(ans==-1) cout<<"No solution"<<endl;
	else cout<<ans<<endl;
}

2.爬楼梯
每次只能爬1,2,3,4个台阶,一共十个台阶,第五个和第七个台阶不能使用,到达第十个台阶的方法种类数。

#include<iostream>

using namespace std;
int f[20];
int main ()
{
    f[0]=0;
    f[1]=1;
    f[2]=2;//1+1
    f[3]=4;//1+2+1
    f[4]=8;//1+2+4+1
    f[5]=0;
    for(int i=6;i<=10;i++)
    {
        if(i==7)continue;
        else f[i]=f[i-1]+f[i-2]+f[i-3]+f[i-4];
    }
    cout<<f[10];
    return 0;
}

3.方阵
广场上的小朋友们排成了整齐的方阵。具体来说,我们可以把每个小朋友看做是一个点,那么小朋友们就形成了 n×n 的点阵。方阵中,小朋友 AA 和小朋友 BB 互相可以看见,当且仅当二人之间的连线不经过别的小朋友,且他们之间的距离不超过 k(因为太远就看不见了)。我们想知道有多少对小朋友互相可以看见。(A,B)与 (B,A) 算同一对。
例如, n=2,k=1 时答案为 4, n=2,k=2时答案为 6(距离为 1的有 4对,距离为 sqrt 2 的有 2 对), n=3,k=2时答案为 20。
现在我们想要知道,当 n=1000,k=5000 时的答案是多少。由于答案过大,请回答对 10^9+7 取模后的结果。

#include<iostream>
using namespace std;
int gcd(int a,int b){return b==0 ?a:gcd(b,a%b);}
long long dist(int a,int b){return a*a+b*b;}
int main ()
{
    long long num=0;
    long long e=1e9+7;
	long long int n,k;
    cin>>n>>k;
    k*=k;
    for(int i=1;i<n;i++)
        for(int j=1;j<n;j++)
    {
        if(gcd(i,j)==1&&dist(i,j)<=k)
            num=(num+(n-j)*(n-i)%e)%e;
    }
    num*=2;
    num+=(2*n*(n-1)%e);
    cout<<num<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值