首页 > 其他分享 >P1141 01迷宫

P1141 01迷宫

时间:2023-01-09 00:00:50浏览次数:48  
标签:search 01 int 迷宫 P1141 build && ans 1005

这题数据有点高级啊(这么高级的数据能不能把它变成黄题呢?不然显得我很垃圾(虽然是事实))

思路

联通块,把周围四格与自己不同的联通起来,看成一个大块,知道要的坐标属于哪个大块并数出大块有多少个点就行了

 

我的第一个想法是先预处理出联通块,然后直接暴力搜索,需要哪个坐标就去搜大块有几个点(想着橙题,随便做都能AC。。

(70分。。

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int b[1005][1005];
bool c[1005][1005];
int n,m;
void build(int x,int y,int k)
{
	if(x>n || x==0) return; if(y>n || y==0) return ;
	b[x][y]=k;
	if(a[x+1][y]!=a[x][y] && !b[x+1][y]) build(x+1,y,k);
	if(a[x-1][y]!=a[x][y] && !b[x-1][y]) build(x-1,y,k);
	if(a[x][y+1]!=a[x][y] && !b[x][y+1]) build(x,y+1,k);
	if(a[x][y-1]!=a[x][y] && !b[x][y-1]) build(x,y-1,k);
}
int search(int x,int y)
{
	int ans=1;
	if(b[x+1][y]==b[x][y] && !c[x+1][y]) {c[x+1][y]=1; ans+=search(x+1,y);}
	if(b[x-1][y]==b[x][y] && !c[x-1][y]) {c[x-1][y]=1; ans+=search(x-1,y);}
	if(b[x][y+1]==b[x][y] && !c[x][y+1]) {c[x][y+1]=1; ans+=search(x,y+1);}
	if(b[x][y-1]==b[x][y] && !c[x][y-1]) {c[x][y-1]=1; ans+=search(x,y-1);}
	return ans;
}
int main()
{
	int x,y,k=1;
	string s;
	cin>>n>>m;
	memset(a,100,sizeof(a));
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		for(int j=0;j<s.size();j++)
		    a[i][j+1]=s[j]-48;
	}//输入的时候是字符串,需要逐字处理 
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	        if(!b[i][j]){
	        	build(i,j,k);
	            k++;
			}//预处理 ,属于同一个大块的都有相同的K值 
	for(int k=1;k<=m;k++)
	{
		cin>>x>>y;
		int ans=0;
		memset(c,0,sizeof(c));
		c[x][y]=1;
		ans=search(x,y);//暴力搜索所属大块有几个点 
		cout<<ans<<endl;
	}
	return 0;
}

  

然后就想着改进:感觉每次都暴力数大块有几个点,假如几个点属于同一大块,不就重复数了吗,既然这样,再预处理一下,直接输出答案不就完美了(想到这,感觉这次肯定能AC了。。

(80分。。 这数据真的高级

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int b[1005][1005];
bool c[1005][1005];
int d[1005][1005];
int n,m;
void build(int x,int y,int k)
{
	if(x>n || x==0) return; if(y>n || y==0) return ;
	b[x][y]=k;
	if(a[x+1][y]!=a[x][y] && !b[x+1][y]) build(x+1,y,k);
	if(a[x-1][y]!=a[x][y] && !b[x-1][y]) build(x-1,y,k);
	if(a[x][y+1]!=a[x][y] && !b[x][y+1]) build(x,y+1,k);
	if(a[x][y-1]!=a[x][y] && !b[x][y-1]) build(x,y-1,k);
}
int search(int x,int y)
{
	int ans=1;
	if(b[x+1][y]==b[x][y] && !c[x+1][y]) {c[x+1][y]=1; ans+=search(x+1,y);}
	if(b[x-1][y]==b[x][y] && !c[x-1][y]) {c[x-1][y]=1; ans+=search(x-1,y);}
	if(b[x][y+1]==b[x][y] && !c[x][y+1]) {c[x][y+1]=1; ans+=search(x,y+1);}
	if(b[x][y-1]==b[x][y] && !c[x][y-1]) {c[x][y-1]=1; ans+=search(x,y-1);}
	return ans;
}
void build1(int x,int y,int k)//预处理,在d数组直接标出属于同一个大块的点的个数 
{
	if(x>n || x==0) return; if(y>n || y==0) return ;
	d[x][y]=k;
    if(b[x+1][y]==b[x][y] && !d[x+1][y]) {d[x+1][y]=k; build1(x+1,y,k);}
	if(b[x-1][y]==b[x][y] && !d[x-1][y]) {d[x-1][y]=k; build1(x-1,y,k);}
	if(b[x][y+1]==b[x][y] && !d[x][y+1]) {d[x][y+1]=k; build1(x,y+1,k);}
	if(b[x][y-1]==b[x][y] && !d[x][y-1]) {d[x][y-1]=k; build1(x,y-1,k);}
}
int main()
{
	int x,y,k=1;
	string s;
	cin>>n>>m;
	memset(a,100,sizeof(a));
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		for(int j=0;j<s.size();j++)
		    a[i][j+1]=s[j]-48;
	}
	for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	        if(!b[i][j]){
	        	build(i,j,k);
	        	memset(c,0,sizeof(c));
	        	c[i][j]=1;
	        	int ans=search(i,j);//搜索出大块有几个点 
	        	build1(i,j,ans);//预处理 
	            k++;
			}
	for(int k=1;k<=m;k++)
	{
		cin>>x>>y;
		cout<<d[x][y]<<endl;//直接输出结果 
	}
	return 0;
}

  

然后实在撑不住,去看了题解。。

每次碰到没搜过的就进行一次搜索,碰到的就直接输出(用数组模拟队列来储存属于同一大块的点的坐标

#include <bits/stdc++.h>
using namespace std;
int a[1005][1005];
int c[1005][1005];
int d[1005][1005];
int xx[10000005],yy[1000005];
int n,m;
void search(int x,int y)
{
	int t=1,h=0,ans=0;
	while(h<t)//bfs的队列 
	{
	    h++;
	    x=xx[h]; y=yy[h];
		if(a[x+1][y]!=a[x][y] && !c[x+1][y] && x+1<=n) {t++; c[x+1][y]=1; xx[t]=x+1; yy[t]=y;}
        if(a[x-1][y]!=a[x][y] && !c[x-1][y] && x-1>0) {t++; c[x-1][y]=1; xx[t]=x-1; yy[t]=y;}
	    if(a[x][y+1]!=a[x][y] && !c[x][y+1] && y+1<=n) {t++; c[x][y+1]=1; xx[t]=x; yy[t]=y+1;}
	    if(a[x][y-1]!=a[x][y] && !c[x][y-1] && y-1>0) {t++; c[x][y-1]=1; xx[t]=x; yy[t]=y-1;}
	    
	}
	for(int i=1;i<=t;i++)
	    d[xx[i]][yy[i]]=t;//每个属于大块的点都标记上大块点的个数 
	return ;
}
int main()
{
	int x,y,k=1;
	string s;
	cin>>n>>m;
	memset(a,100,sizeof(a));
	for(int i=1;i<=n;i++)
	{
		cin>>s;
		for(int j=0;j<s.size();j++)
		    a[i][j+1]=s[j]-48;
	}
	for(int k=1;k<=m;k++)
	{
		cin>>x>>y;
		if(!d[x][y]) {c[x][y]=1; xx[1]=x; yy[1]=y; search(x,y);}//如果没搜过就搜 
		cout<<d[x][y]<<endl; 
	}
	return 0;
}

  

 

标签:search,01,int,迷宫,P1141,build,&&,ans,1005
From: https://www.cnblogs.com/wdxxz3274/p/17035795.html

相关文章

  • [2019强网杯]随便注
    [2019强网杯]随便注考点:1、堆叠注入 2、sql预处理语句之前做过的一道题,再次遇到发现还是有很多需要学习的地方,也没有记录过堆叠注入的题,所以就想着记一下这道题的一些知......
  • [强网杯 2019]Upload
    [强网杯2019]Upload考点:1、文件上传 2、php反序列化攻击进到页面里,存在注册功能,所以就不尝试先不尝试sql注入,先注册一个账号登陆进去进去之后有一个上传文件功能,尝试上......
  • [CISCN2019 华东南赛区]Double Secret
    [CISCN2019华东南赛区]DoubleSecret考点:1、RC4加密 2、FlaskのSSTI进去一脸懵逼,常规流程走一套啥也没发现然后先是看到了毫无用处的robots.txt,dirsearch扫了一遍也没......
  • [HarekazeCTF2019]encode_and_encode
    [HarekazeCTF2019]encode_and_encode考点:json_decode的unicode编码绕过进入题目后,很容易就可以看到源码query.php<?phperror_reporting(0);if(isset($_GET['source'......
  • [NCTF2019]SQLi
    [NCTF2019]SQLi考点:sqlbypass一道sql题,非常友好的给出了sqlquery,但想必也不简单sqlquery:select*fromuserswhereusername='1'andpasswd='1'这中语句非常典......
  • [SWPUCTF 2018]SimplePHP
    [SWPUCTF2018]SimplePHP考点:1、PHP代码审计 2、Phar反序列化漏洞网站中有两个功能:查看文件和上传文件,利用查看文件将源码都先弄下来进行PHP代码审计。file.php<?php......
  • [SUCTF 2019]EasyWeb
    [SUCTF2019]EasyWeb考点:1、文件上传bypass 2、.htaccess的利用开局源代码<?phpfunctionget_the_flag(){//webadminwillremoveyouruploadfileevery20m......
  • 12.30-0108文献阅读总结
      本周是论文研读第一周,可是一篇都没有仔细读完,怎样才算仔细研读呢,心里的标准是这样的:  1、从一定程度上区分筛选出好论文;  2、对作者及研究机构分析,在大实验的官......
  • GB/T 35279-2017 信息安全技术 云计算安全参考架构 附录下载地址
    声明本文是学习​​GB-T35279-2017信息安全技术云计算安全参考架构.下载地址http://github5.com/view/594​​而整理的学习笔记,分享出来希望更多人受益,如果存在侵权......
  • 230108_50_RPC底层原理
    Stub还有很多需要优化的地方,目前只是实现了一个最基本的代理。网络传输都是通过序列化和反序列化进行的,目前java自带的Serializable接口效率比较低,因此可以对rpc的序列化......