郑大战役杯邀请赛(第三次)

13 篇文章 0 订阅

由于防控形势严峻,现在z市已经开始了全区域的网格化封控管理。该市的区域可以看成一个矩形,其中所有主干道都是水平或垂直的,并且贯穿整个区域。如图所示,黑色表示城区的边界,红色表示城区的主干道,其中边界和主干道宽度都为1,且不存在边界与主干道、主干道与主干道相邻的情况

2e42aec3ff2596d217b51a177d4d538a.png

为了方便网格化管理,我们定义网格单元是由城区边界或主干道围成的区域,且任意网格单元内不能包含主干道。上图中,该城区共被分割成了16个网格单元。

现在给出该区域的地图,需要你统计出该城区划分出了多少个网格单元,以方便安排医务人员和应急物资。

在计算机中,图像的本质就是二维的矩阵。为了方便处理,我们将上述图像中城区边界及里面的内容转化为了二维字符矩阵,详细见输入格式描述。

输入格式:

第一行输入两个整数n,m(3≤n,m≤100)
其后n行,每行m个字符,字符有'*'和'#'两种。'*'代表城区边界或主干道,'#'代表网格单元内区域。

输出格式:

输出一行一个整数,代表地图中的网格单元个数。

输入样例:

3 7
*******
*##*##*
*******

输出样例:

2

 

说实话,第一眼看到我根本没看懂什么意思,看了好一会才发现只要数出#有多少个就可以了,但是这里的#必须是不连接在一起的,那么很简单的就能发现是个简单的连通块问题,图都算不上。

具体的方法是:找到#号以后,进行dfs,查找他周围的所有#,打上标记,防止二次记录即可;

因为数据不大,这种写法也不难,所以很轻松就可以过掉

代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

char arr[110][110];
int n,m;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};
bool st[110][110];

void pd(int x,int y)
{
	st[x][y]=true;
	for(int i=0;i<4;i++)
	{
		int xx=x+dx[i],yy=y+dy[i];
		if(xx>=0&&xx<n&&yy>=0&&yy<m&&arr[xx][yy]=='#'&&st[xx][yy]==false)//不要忘记判断 
		pd(xx,yy);
	}
}

int main()
{
	
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			cin>>arr[i][j];
	
	int ans=0;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(arr[i][j]=='*')
			continue;
			else if(arr[i][j]=='#'&&st[i][j]==false)
			{
				ans++;
				pd(i,j);//进行标记,我们这里采用打表的方法 
			}
		}
	}
	cout<<ans;//直接输出即可 
} 

由于防控形势严峻,现在z市已经开始了全区域的网格化封控管理。该市的区域可以看成一个矩形,其中所有主干道都是水平或垂直的,并且贯穿整个区域。如图所示,黑色表示城区的边界,红色表示城区的主干道。其中边界和主干道宽度都为1,且不存在边界与主干道、主干道与主干道相邻的情况。

8770b1047cd8433e4b79d38314595937.png

为了方便网格化管理,我们定义网格单元是由城区边界或主干道围成的区域,且任意网格单元内不能包含主干道。上图中,该城区共被分割成了16个网格单元。

同时,网格化管理的本质思想是“分治”,不同的划分粒度对于管理效率会产生深远的影响。所以,这次W同学思考的不仅仅是网格单元,而是子网格。

子网格的定义为:子网格也是一个矩形,且子网格矩形4个角的对应点都位于边界与边界、边界与主干道、主干道与主干道的交点上。我们认为两个子网格是相同的,当且仅当两个子网格的4个角对应点全部重合。根据这个定义,我们可以知道,任意的网格单元也是一种子网格,整个城区的矩形也是一种特殊的子网格。

同样给出上述的图像,你能否帮小W计算下,有多少种可能的子网格?

输入格式:

第一行输入两个整数n,m(3≤n,m≤100)
其后n行,每行m个字符,字符有'*'和'#'两种。'*'代表城区边界或主干道,'#'代表网格单元内区域。

输出格式:

输出一行一个整数,代表符合条件不同子网格的个数。

输入样例:

3 7
*******
*##*##*
*******

输出样例:

3

 

这道题我估计大家看到的第一眼就是:懵逼...

我也是,在求助一位卫姓大佬后,我得到了做题的方法,我们只要在里面找到一个矩形,这个矩形的边上不能有网格单元,这样的一个图就是我们的答案,但是这里我们要找的是所有的矩形,所以我们也要考虑到两个矩形连接其实是一个大矩形的问题;

eg:69da08e8ab864242bd76b9ce60c1017e.png

 红线就是我们的边,这里我们数一下,很简单就发现有两个矩形,加一个大矩形,为3个;

这道题有歧义,我的写法是有问题的,但是估计出题人也没想到,所以也就那样了;

我的想法是把有#的的那一行一列的*全去掉,这样可以减少判断,再去判断*,但是这里会有错误的数据,所以这个写法有问题的,大家看看就行了;真写的话就去掉查找#的那一步再写一写。

错误数据eg(不在考试时的数据里):

ec2e440bc0e2427dbb1f9981c62aaa20.png这个数据不只1个,但是我的程序出来一个,程序交上去还对了,所以这里其实是有问题的;

 

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

char arr[110][110];
int n,m,ans=0;
bool st[110][110];

void quchu(int x,int y)
{
	for(int i=0;i<m;i++)
		st[x][i]=true;
	for(int i=0;i<n;i++)
	    st[i][y]=true;
}

void dfs(int x,int y)
{
	for(int i=x;i<n;i++)
	{
		for(int j=y;j<m;j++)
		{
			if(arr[i][j]=='*'&&i!=x&&j!=y&&st[i][j]==false)
			ans++;
		}
	}
}

int main()
{
	
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			cin>>arr[i][j];
//		
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			if(arr[i][j]=='#')
			quchu(i,j);
			
//	for(int i=0;i<n;i++)
//	{
//		for(int j=0;j<m;j++)
//		{
//			if(st[i][j]==false)
//			cout<<"0";
//			else 
//			cout<<"1";
//		}
//		cout<<endl;
//	}
		
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(st[i][j]==false)
			dfs(i,j);
		}
	}
	cout<<ans;
} 

疫情来了,柴刘青山在寝室关着非常无聊,和室友一起玩跑跑卡丁车这款老游戏。

这款游戏有一个模式叫做组队竞速,每局8个人,分为两队,最终比拼哪队总分更高。

第一名冲线得到8分,第二名得到7分,以此类推,第八名得到1分。

柴刘青山好奇自己队伍在某一局游戏中是否能得到某个总分,如果可以,有多少种排名情况可以达成该总分?

后记:柴刘青山和室友们寻求过短暂的放松后,决定还是在学业上开启“竞速模式”,约定共同努力学习,参加“战疫杯”!

输入格式:

第一行一个正整数n,表示猜想的n总分。 0≤n≤10000

输出格式:

如果可以达成,输出一个正整数x,代表有多少种排名情况。
如果不能达成,输出NO。

输入样例:

25

输出样例:

1

样例解释1

柴刘青山的队伍需要取得1、2、3、5名,对应8+7+6+4=25。有且仅有这一种情况。

这道题没什么可说的啊,找到1-8中所有4个数的组合,求一下加法判断与所给的数相不相同即可,dfs创造四个数的组合,当然也有其他方法,剪不剪枝都无所谓,反正数据够小,不剪枝加一步判断即可;

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

bool st[9];
int n,ans=0;

int dfs(int k)//dfs创造4个数的组合
{
	if(k==9)
	{
		int o=0,cnt=0;
		for(int i=1;i<=8;i++)//不剪枝就判断
		if(st[i]==false)
		o++,cnt+=i;
		if(o==4&&cnt==n)
		ans++;
		
	}
	else 
	{
		for(int i=0;i<=1;i++)
		{
			st[k]=i;
			dfs(k+1);
		}
	}
}
int main()
{
	cin>>n;
	dfs(1);
	cout<<ans;
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值