CCF-CSP 202206-2 寻宝!大冒险!

 题意较长,注意好好理解再动手,首先可以简单概括一下题意就是给你一个大小一定的子数组,去匹配一个大数组中有多少个匹配的,匹配条件如下

 此外需要强调的是这句话:特别地,藏宝图左下角位置一定是一棵树

第一思路:

第一想法是想创建两个数组来存储两张图,然后,遍历“绿化图”中每一个点作为起点(这里我当时没注意到“藏宝图左下角位置一定是一棵树”,实际上只需遍历为1的点作为左下角即可),然后遍历藏宝图,将藏宝图中的坐标与绿化图中的坐标相互转换,即藏宝图中的点(p,q),对应绿化图中的点(i+p,j+q)其中(i,j)为绿化图中的左下角的点,匹配的过程中如果发现不匹配就break,如果完美匹配就ans++即可

这里还要强调的点是

这句话,表明我们在输入数组时需要将上下进行颠倒过来 

#include<iostream>

using namespace std;

int n,L,S,ans=0;
//int index1[2005];
//int index2[2005];
int mapp1[2005][2005];
int mapp2[55][55];
int main(){
	cin>>n>>L>>S;
	for(int i=0;i<n;i++){
		int v,w;
		cin>>v>>w;
		mapp1[v][w]=1;
	}
	for(int i=S;i>=0;i--){
		for(int j=0;j<=S;j++){
			cin>>mapp2[i][j];
		}
	}
	for(int i=0;i<=L-S;i++){
		for(int j=0;j<=L-S;j++){//枚举每一个点作为藏宝图的左下角 
			int sign=0;//判断是否可能有宝藏 
			for(int p=0;p<=S;p++){//遍历以(i,j)为左下角的藏宝图与绿化图 
				for(int q=0;q<=S;q++){
					if(mapp1[i+p][j+q]!=mapp2[p][q]){
						sign=1;
						break;
					}
				}
				if(sign){
					break;
				}
			} 
			if(!sign){
				ans++;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

因为这里为绿化图也建立了一个数组,所以最多只能拿到70分

后面仔细思考后的思路更清晰一些

首先,上面的思路选择在一开始就不正确,我们不应该也不必要为绿化图建立数组,因为遍历左下角的点只需遍历值为1的点即可,而这在输入中已经知道了,因此只需O(n)遍历即可,此外,我们还要保证选择的点作为左下角之后能否在右上角容纳下宝藏图,如果不能,则continue,反之则需要对两张图进行匹配,这里匹配两个数组对应的点是否相等,我们只需判断绿化图中的点是否在index数组中,如果在就相当于判断藏宝图中的点是否为1即可,不在index数组中则同理判断藏宝图中的点是否为0即可

#include<iostream>

using namespace std;

int n,L,S,ans=0;
int index1[1005];
int index2[1005];
int mapp2[55][55];

bool check(int x1,int y1,int x2,int y2){
	//检查(x1,x2)与(x2,y2)是否匹配 
	for(int i=0;i<n;i++){
		if(index1[i]==x1&&index2[i]==y1){
			return 1==mapp2[x2][y2];
		}//如果(x1,y1)在index数组中则值为1,就看mapp2[x2][y2]是否为1 
	}
	return 0==mapp2[x2][y2];//同理 
}

int main(){
	cin>>n>>L>>S;
	for(int i=0;i<n;i++){
		cin>>index1[i]>>index2[i];
	}
	for(int i=S;i>=0;i--){
		for(int j=0;j<=S;j++){
			cin>>mapp2[i][j];
		}
	}
	for(int i=0;i<n;i++){//枚举左下角的点 
		//题目说了 藏宝图左下角位置一定是一棵树 
		int len1=index1[i]+S,len2=index2[i]+S;
		if(len1>L||len2>L){//如果以当前点作为左下角的点越界了 
			continue;
		}else{
			int sign=0;
			for(int p=0;p<=S;p++){
				for(int q=0;q<=S;q++){
					if(!check(index1[i]+p,index2[i]+q,p,q)){
						sign=1;
						break;
					}		
				}
				if(sign){
					break;
				}
			} 
			if(!sign){
				ans++;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

该篇博客的思路与我相近,但写得比我好,可供参考

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZZWWWFFF_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值