XDOJ 相邻区域(序号71)题解
题目如下:
一个n行m列的矩阵被划分成t个矩形区域,分别用数字1-t来标识,同一个区域内的元素都用同一个数字标识。如下图所示,一个6行8列的矩阵被分成8个矩形区域,分别用编号1-8标识。当两个小区域之间公用一条边时,称这两个区域相邻,例如下图中区域5的相邻区域有6个,分别为1,2,3,6,7,8,但4并不是它的相邻区域。请写一个程序找出区域k的所有相邻区域。
输入说明:
输入第一行为四个整数n,m, t,k,整数之间用空格分隔。n表示矩阵行数(n<20),m表示矩阵列数(m<20),t表示矩阵被划分为t个矩形区域(0<t<50),k为其中某个区域的编号(1<=k<=t)。接下来是n行数据,每行m个整数,表示矩阵内各个元素所在的区域,整数之间用空格分开。
输出说明:
输出为一个整数,表示与k相邻的区域个数。
输入样例
6 8 8 5
1 1 2 2 2 3 3 4
1 1 2 2 2 3 3 4
1 1 2 2 2 3 3 4
1 1 5 5 5 5 5 6
1 1 5 5 5 5 5 6
7 7 7 7 7 8 8 8
输出样例
6
这个题目很好理解,就是给你一坨二维数组,将其分为了t个矩形块,并且替你标好了编号,指定一个编号,让你找到所有与目标矩形块相邻的矩形块,并输出矩形块的数量。
关键点如下:
- 所有区块均是矩形块,这一点大大减少了代码量以及思考量
- 因为是矩形块,我们只需要找到目标编号的矩形的四个顶点的位置,就能确定目标位置
- 确定四个顶点之后,只需要对目标矩形块相邻的上下左右四个边的数据进行循环判断其编号类型即可
代码如下:(因为XDer统一学C,所以就贴C了)
#include<stdio.h>
int main()
{
int m,n;
scanf("%d%d",&n,&m);//读入行,列
int a[n][m];
int i,j,k,t;
int x,y=0;
scanf("%d%d",&t,&k);//读入总矩形块数目和目标编号
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
}
}
int flag1=-1,flag2=-1,flag3=-1,flag4=-1;//1是左上角,2是右上角,3是左下角,4是右下角
for(i=0;i<n;i++)//确定两个顶点
{
for(j=0;j<m;j++)
{
if(a[i][j]==k)
{
flag1=j;
flag3=i;
break;
}
}
if(flag1!=-1)
break;
}
for(i=0;i<n;i++)//确定右上角
{
for(j=0;j<m;j++)
{
if(a[i][j]==k)
{
if(j+1==m||a[i][j+1]!=k)
{
flag2=j;
break;
}
}
}
if(flag2!=-1)
break;
}
for(i=0;i<n;i++)//确定右下角
{
for(j=0;j<m;j++)
{
if(a[i][j]==k)
{
if(i+1==n||a[i+1][j]!=k)
{
flag4=i;
break;
}
}
}
if(flag4!=-1)
break;
}
int b[t+1];//定义一个新的数组b,作为标记数组,如果对矩形块四边循环时出现了对应编号的代码,则标记为1
for(i=0;i<t+1;i++)//变量数组不能在定义时赋值,所以单独赋值
{
b[i]=0;
}
for(i=flag1;i<=flag2;i++)//循环上边
{
if(flag3==0)
break;
else
{
x=a[flag3-1][i];
b[x]=1;
}
}
for(i=flag1;i<=flag2;i++)//循环下边
{
if(flag4+1==n)
break;
else
{
x=a[flag4+1][i];
b[x]=1;
}
}
for(i=flag3;i<=flag4;i++)//循环左边
{
if(flag1==0)
break;
else
{
x=a[i][flag1-1];
b[x]=1;
}
}
for(i=flag3;i<=flag4;i++)//循环右边
{
if(flag2+1==m)
break;
else
{
x=a[i][flag2+1];
b[x]=1;
}
}
for(i=0;i<t+1;i++)对b数组进行加法,结果即为相邻区域的数目
{
y+=b[i];
}
printf("%d",y);
return 0;
}
代码中小细节有很多,还需要自行学习,我不再一一赘述。