noi题库(noi.openjudge.cn) 1.8编程基础之多维数组T11——T20

T11 图像旋转

描述

输入一个n行m列的黑白图像,将它顺时针旋转90度后输出。

输入

第一行包含两个整数n和m,表示图像包含像素点的行数和列数。1 <= n <= 100,1 <= m <= 100。
接下来n行,每行m个整数,表示图像的每个像素点灰度。相邻两个整数之间用单个空格隔开,每个元素均在0~255之间。

输出

m行,每行n个整数,为顺时针旋转90度后的图像。相邻两个整数之间用单个空格隔开。

样例输入
3 3
1 2 3
4 5 6
7 8 9
样例输出
7 4 1
8 5 2
9 6 3

样例

以矩阵元素坐标为例:

1,1    1,2    1,3    顺时针旋转后为    2,1    1,1

2,1    2,2    2,3                           2,2    1,2

2,3    1,3

所以输出时第一重循环i正着循环每一列,第二重循环j倒着循环每一行,依次输出(j,i)

 1 #include<iostream>
 2 using namespace std;
 3 int n,m,a[101][101];
 4 int main()
 5 {
 6     cin>>n>>m;
 7     for(int i=1;i<=n;i++)
 8      for(int j=1;j<=m;j++)
 9       cin>>a[i][j];
10     for(int i=1;i<=m;i++)
11      {
12          for(int j=n;j>=1;j--)
13          cout<<a[j][i]<<‘ ‘;
14         cout<<endl;
15      }
16 }

T12 变换的矩阵

描述

有一个N x N(N为奇数,且1 <= N <= 10)的矩阵,矩阵中的元素都是字符。这个矩阵可能会按照如下的几种变幻法则之一进行变幻(只会变幻一次)。

现在给出一个原始的矩阵,和一个变幻后的矩阵,请编写一个程序,来判定原始矩阵是按照哪一种法则变幻为目标矩阵的。

1. 按照顺时针方向旋转90度; 
如:

1 2 3        7 4 1
4 5 6 变幻为  8 5 2
7 8 9        9 6 3

2. 按照逆时针方向旋转90度; 
如:

1 2 3        3 6 9
4 5 6 变幻为  2 5 8
7 8 9        1 4 7

3. 中央元素不变(如下例中的 5),其他元素(如下例中的3)与“以中央元素为中心的对应元素”(如下例中的7)互换; 
如:

1 2 3       9 8 7
4 5 6 变幻为 6 5 4
7 8 9       3 2 1

4. 保持原始矩阵,不变幻;

5. 如果 从原始矩阵 到 目标矩阵 的变幻,不符合任何上述变幻,请输出5


输入

第一行:矩阵每行/列元素的个数 N;
第二行到第N+1行:原始矩阵,共N行,每行N个字符;
第N+2行到第2*N+1行:目标矩阵,共N行,每行N个字符;

输出

只有一行,从原始矩阵 到 目标矩阵 的所采取的 变幻法则的编号。

样例输入
5
a b c d e
f g h i j
k l m n o
p q r s t
u v w x y
y x w v u
t s r q p
o n m l k
j i h g f
e d c b a
样例输出
3

样例

方法1(比较麻烦,但是快用时1ms,时间复杂度n2—4n2):记录下原始矩阵每一种变换情况后的矩阵,然后与目标矩阵对比

1,1    1,2    1,3    顺时针旋转后为    2,1    1,1

2,1    2,2    2,3                            2,2    1,2

2,3    1,3

所以记录时第一重循环i正着循环每一列,第二重循环j倒着循环每一行,依次记录a[j][i]

1,1    1,2    1,3  逆时针旋转后为     1,3   2,3

2,1    2,2    2,3                           1,2   2,2

1,1   2,1

所以记录时第一重循环i正着循环每一行,第二重循环j倒着循环每一列,依次记录a[i][j]

情况3也就是将整个矩阵旋转180°,所以记录时两重循环都倒着循环

 1 #include<iostream>
 2 #include<cstdlib>
 3 using namespace std;
 4 int n;
 5 char a[11][11],b[11][11],c[11][11];
 6 void case1()
 7 {
 8     int x=0,y=0;
 9     for(int i=1;i<=n;i++)
10      {
11          x++;y=0;
12          for(int j=n;j>=1;j--)
13            c[x][++y]=a[j][i];
14         for(int k=1;k<=n;k++)
15          if(c[x][k]!=b[x][k])
16            return;
17      }
18     cout<<‘1‘;
19     exit(0);
20 }
21 void case2()
22 {
23     int x=0,y=0;
24     for(int i=n;i>=1;i--)
25      {
26          x++;y=0;
27          for(int j=1;j<=n;j++)
28           c[x][++y]=a[j][i];
29          for(int k=1;k<=n;k++)
30           if(c[x][k]!=b[x][k])
31            return ;
32      }
33     cout<<‘2‘;
34     exit(0);
35 }
36 void case3()
37 {
38     int x=0,y=0;
39     for(int i=n;i>=1;i--)
40      {
41          x++;y=0;
42          for(int j=n;j>=1;j--)
43           c[x][++y]=a[i][j];
44          for(int k=1;k<=n;k++)
45           if(c[x][k]!=b[x][k])
46            return;
47      }
48     cout<<‘3‘;
49     exit(0);
50 }
51 void case4()
52 {
53     for(int i=1;i<=n;i++)
54      for(int j=1;j<=n;j++)
55       if(a[i][j]!=b[i][j])
56        return;
57     cout<<‘4‘;
58     exit(0);
59 }
60 int main()
61 {
62     cin>>n;
63     for(int i=1;i<=n;i++)
64      for(int j=1;j<=n;j++)
65       cin>>a[i][j];
66     for(int i=1;i<=n;i++)
67      for(int j=1;j<=n;j++)
68       cin>>b[i][j];
69     case1();
70     case2();
71     case3();
72     case4();
73     cout<<‘5‘;
74     return 0;
75 }

1

方法2(代码较短,但慢一点,9ms,时间复杂度,固定4n2):

省去方法1中的记录,直接根据目标矩阵与原矩阵变换后元素的位置关系判断。所以需要判断完所有位置才能出结果

顺时针旋转目标数组b[i][j]对应原数组a[n-j+1][i]

逆时针旋转目标数组b[i][j]对应原数组a[j][n-i+1]

中心对称目标数组b[i][j]对应原数组a[n-i+1][n-j+1]

 1 #include<iostream>
 2 using namespace std;
 3 int n;
 4 char a[101][101],b[101][101];
 5 bool p[5];
 6 int main()
 7 {
 8     cin>>n;
 9     for(int i=1;i<=n;i++)
10      for(int j=1;j<=n;j++)
11       cin>>a[i][j];
12     for(int i=1;i<=n;i++)
13      for(int j=1;j<=n;j++)
14       cin>>b[i][j];
15     for(int i=1;i<=n;i++)
16      for(int j=1;j<=n;j++)
17      {
18          if(b[i][j]!=a[n-j+1][i]) p[1]=true;
19          if(b[i][j]!=a[j][n-i+1]) p[2]=true;
20          if(b[i][j]!=a[n-i+1][n-j+1]) p[3]=true;
21          if(b[i][j]!=a[i][j]) p[4]=true;
22      }
23      for(int i=1;i<=4;i++)
24       if(!p[i])
25        {
26               cout<<i;return 0;
27        }
28     cout<<‘5‘;
29 }

T13 图像模糊处理

描述

给定n行m列的图像各像素点的灰度值,要求用如下方法对其进行模糊化处理:

1. 四周最外侧的像素点灰度值不变;

2. 中间各像素点新灰度值为该像素点及其上下左右相邻四个像素点原灰度值的平均(舍入到最接近的整数)。

输入

第一行包含两个整数n和m,表示图像包含像素点的行数和列数。1 <= n <= 100,1 <= m <= 100。
接下来n行,每行m个整数,表示图像的每个像素点灰度。相邻两个整数之间用单个空格隔开,每个元素均在0~255之间。

输出

n行,每行m个整数,为模糊处理后的图像。相邻两个整数之间用单个空格隔开。

样例输入
4 5
100 0 100 0 50
50 100 200 0 0
50 50 100 100 200
100 100 50 50 100
样例输出
100 0 100 0 50
50 80 100 60 0
50 80 100 90 200
100 100 50 50 100

样例

四舍五入可以用函数round,也可以用printf(”.0lf“,x);

 1 #include<iostream>
 2 #include<cmath>
 3 using namespace std;
 4 int n,m,a[101][101],b[101][101];
 5 int main()
 6 {
 7     cin>>n>>m;
 8     for(int i=1;i<=n;i++)
 9      for(int j=1;j<=m;j++)
10       cin>>a[i][j];
11     for(int i=1;i<=n;i++)
12      for(int j=1;j<=m;j++)
13       {
14             if(i==1||i==n||j==1||j==m)
15              b[i][j]=a[i][j];
16             else
17              {
18                double r=((double)a[i][j]+a[i-1][j]+a[i+1][j]+a[i][j-1]+a[i][j+1])/5;
19              b[i][j]=round(r);
20            }
21       }
22      for(int i=1;i<=n;i++)
23       {
24            for(int j=1;j<=m;j++)
25           cout<<b[i][j]<<‘ ‘;
26          cout<<endl;
27       }
28 }

T14 扫雷游戏地雷数计算

描述

扫雷游戏是一款十分经典的单机小游戏。它的精髓在于,通过已翻开格子所提示的周围格地雷数,来判断未翻开格子里是否是地雷。

现在给出n行m列的雷区中的地雷分布,要求计算出每个非地雷格的周围格地雷数。

注:每个格子周围格有八个:上、下、左、右、左上、右上、左下、右下。

输入

第一行包含两个整数n和m,分别表示雷区的行数和列数。1 <= n <= 100, 1 <= m <= 100。
接下来n行,每行m个字符,‘*’表示相应格子中是地雷,‘?’表示相应格子中无地雷。字符之间无任何分隔符。

输出

n行,每行m个字符,描述整个雷区。若相应格中是地雷,则用‘*’表示,否则用相应的周围格地雷数表示。字符之间无任何分隔符。

样例输入
3 3
*??
???
?*?
样例输出
*10
221
1*1

样例

两种思路:1、统计出每个地雷的位置,以地雷为基准,周围8个非地雷的格子+1。预测应该比第二种方法快

2、以每一个格子为基准,枚举周围8个格子。时间复杂度O(8n2)

在此只提供第一种方法的代码

 1 #include<iostream>
 2 using namespace std;
 3 int n,m,b[101][101],cnt;
 4 int dx[8]={-1,-1,-1,0,1,1,1,0};
 5 int dy[8]={-1,0,1,1,1,0,-1,-1};
 6 int x[10001],y[10001];
 7 char a[101][101];
 8 int main()
 9 {
10     cin>>n>>m;
11     for(int i=1;i<=n;i++)
12      for(int j=1;j<=m;j++)
13       {
14            cin>>a[i][j];
15            if(a[i][j]==‘*‘)
16            {
17                x[++cnt]=i;y[cnt]=j;
18          }
19       }
20     for(int i=1;i<=cnt;i++)
21     {
22         int xx=x[i],yy=y[i];
23         for(int j=0;j<8;j++)
24         {
25             int nx=xx+dx[j],ny=yy+dy[j];
26             if(nx>0&&nx<=n&&ny>0&&ny<=m&&a[nx][ny]!=‘*‘)
27                 b[nx][ny]++;
28         }
29     }
30     for(int i=1;i<=n;i++)
31      {
32           for(int j=1;j<=m;j++)
33            if(a[i][j]==‘*‘) cout<<‘*‘;
34            else cout<<b[i][j];
35          cout<<endl;
36      }
37 }

T15 细菌的繁殖与扩散

描述

在边长为9的正方形培养皿中,正中心位置有m个细菌。假设细菌的寿命仅一天,但每天可繁殖10个后代,而且这10个后代,有两个分布在原来的单元格中,其余的均匀分布在其四周相邻的八个单元格中。求经过n(1≤n≤4)天后,细菌在培养皿中的分布情况。

输入

输入为两个整数,第一个整数m表示中心位置细菌的个数(2 ≤ m ≤ 30),第二个整数n表示经过的天数(1 ≤ n ≤ 4)。

输出

输出九行九列整数矩阵,每行的整数之间用空格分隔。整个矩阵代表n天后细菌在培养皿上的分布情况。

样例输入
2 1
样例输出
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 2 2 2 0 0 0
0 0 0 2 4 2 0 0 0
0 0 0 2 2 2 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

样例

三维数组a[k][i][j]代表第k天后矩阵[i,j]位置的细菌数,每次更新时,由于细菌寿命只有一天,所以新的a[k][i][j]=a[k-1][i][j]*2+a[k-1][ni][nj],ni,nj为[i,j]周围的八个单元格

 1 #include<iostream>
 2 using namespace std;
 3 int m,n;
 4 int dx[8]={-1,-1,-1,0,1,1,1,0};
 5 int dy[8]={-1,0,1,1,1,0,-1,-1};
 6 int a[5][10][10];
 7 int main()
 8 {
 9     cin>>m>>n;
10     a[0][5][5]=m;
11     for(int k=1;k<=n;k++)//枚举每一天
12     {
13         for(int i=1;i<=9;i++)
14          for(int j=1;j<=9;j++)//枚举每个单元格
15          {
16              a[k][i][j]=2*a[k-1][i][j];//留在原单元格的2个
17             for(int l=0;l<8;l++)//周围的8个单元格
18            {
19                 int nx=i+dx[l],ny=j+dy[l];
20                 if(nx>0&&nx<=9&&ny>0&&ny<=9)
21                 a[k][i][j]+=a[k-1][nx][ny];
22             }
23          }
24     }
25     for(int i=1;i<=9;i++)
26     {
27         for(int j=1;j<=9;j++)
28         cout<<a[n][i][j]<<‘ ‘;
29         cout<<endl;
30     }
31 }

上面的代码是9ms,下面这个是0ms,搞不懂哪里拖延了时间,期待各位的指点

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int G[15][15],m,n,a[15][15],dx[]={0,0,1,-1,1,-1,1,-1},dy[]={-1,1,0,0,1,-1,-1,1};
 4 int main()
 5 {
 6       cin>>m>>n;G[5][5]=m;
 7       while(n--)
 8       {
 9          memset(a,0,sizeof(a));
10          for(int i=1;i<=9;i++)
11            for(int j=1;j<=9;j++)
12             {
13               a[i][j]+=G[i][j]*2;
14               for(int k=0;k<8;k++)
15               a[i+dx[k]][j+dy[k]]+=G[i][j];
16             }
17          memcpy(G,a,sizeof(a));
18      }
19      for(int i=1;i<=9;i++)
20       {
21           for(int j=1;j<=9;j++)
22            cout<<G[i][j]<<‘ ‘;
23           cout<<endl;
24       }
25      return 0;
26 }

2

T16 矩阵石头剪刀布

描述

Bart的妹妹Lisa在一个二维矩阵上创造了新的文明。矩阵上每个位置被三种生命形式之一占据:石头,剪刀,布。每天,上下左右相邻的不同生命形式将会发生战斗。在战斗中,石头永远胜剪刀,剪刀永远胜布,布永远胜石头。每一天结束之后,败者的领地将被胜者占领。

你的工作是计算出n天之后矩阵的占据情况。

输入

第一行包含三个正整数r,c,n,分别表示矩阵的行数、列数以及天数。每个整数均不超过100。
接下来r行,每行c个字符,描述矩阵初始时被占据的情况。每个位置上的字符只能是R,S,P三者之一,分别代表石头,剪刀,布。相邻字符之间无空格。

输出

输出n天之后的矩阵占据情况。每个位置上的字符只能是R,S,P三者之一,相邻字符之间无空格。

样例输入
3 3 1
RRR
RSR
RRR
样例输出
RRR
RRR
RRR

样例

a[k][i][j]代表第k天,矩阵[i,j]的字符

枚举每一天每一对格子的情况,因为它只会被能够赢它的字符更新,且能更新它的字符只有一个,所以可以每次在四周找能更新它的字符,找到更新,找不到就保持原状

因为R,S,P互相都有胜负关系,所以每一天每个格子只能被更新一次,所以更新了可以立刻停止对这个格子四周的搜索。例:R遇到P,R在今天结束时更新成P,但今天这个格子遇到R,平局,遇到S,胜利,自己不会被更新

所以确定a[k][i][j]时,要由a[k-1][i-1][j],a[k-1][i][j+1],a[k-1][i+1][j],a[k-1][i][j-1]决定,注意是k-1,即上一天的情况。例:PRS,P可以更新R,R可以更新S,由于枚举的顺序,所以先变成PPS,然后枚举到S时,因为这还是同一天,所以要用原来的R来更新S,而不是用S来更新P

由于a[k][i][j]的情况只与a[k-1][][]有关,所以可以用滚动数组优化空间

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int r,c,n;
 5 int dx[4]={-1,0,1,0};
 6 int dy[4]={0,1,0,-1};
 7 char a[2][110][110];
 8 void work(int last/*滚动数组*/,int h/*行*/,int l/*列*/,char win/*目标字符,即可以更新它的字符*/)
 9 {
10     int now=(last+1)%2;
11     int ok=0;
12     for(int i=0;i<4;i++)
13     {
14         if(a[last][h+dx[i]][l+dy[i]]==win)  ok=1,a[now][h][l]=win;
15         if(ok) break;//更新了便可退出
16     }
17     if(!ok) a[now][h][l]=a[last][h][l];
18 }
19 int main()
20 {
21     cin>>r>>c>>n;
22     for(int i=1;i<=r;i++)
23      for(int j=1;j<=c;j++)
24       cin>>a[0][i][j];
25     for(int k=1;k<=n;k++)
26     {
27         memset(a[k%2],‘\0‘,sizeof(a[k%2]));//滚动数组要初始化
28         for(int i=1;i<=r;i++)
29          for(int j=1;j<=c;j++)
30           switch(a[(k-1)%2][i][j])
31           {
32                case ‘R‘:work((k-1)%2,i,j,‘P‘);break;//解释:若这个格子为R,那要以这个格子的坐标为基准,在四周找能更新它的P
33                case ‘S‘:work((k-1)%2,i,j,‘R‘);break;
34                case ‘P‘:work((k-1)%2,i,j,‘S‘);break;
35           }
36     }
37     for(int i=1;i<=r;i++)
38      {
39          for(int j=1;j<=c;j++)
40          cout<<a[n&1][i][j];
41          cout<<endl;
42      }
43 }

起初滚动数组的更新误放到了work函数里,应该在这一天还未开始时清空掉上两天的数据,即每天更新一次,放在work函数里成了每枚举一个格子更新一次

T17 最好的草

描述

奶牛Bessie计划好好享受柔软的春季新草。新草分布在R行C列的牧场里。它想计算一下牧场中的草丛数量。

在牧场地图中,每个草丛要么是单个“#”,要么是有公共边的相邻两个“#”。给定牧场地图,计算有多少个草丛。

例如,考虑如下5行6列的牧场地图

.#......#.....#..#...##..#....

这个牧场有5个草丛:一个在第一行,一个在第二列横跨了二、三行,一个在第三行,一个在第四行横跨了四、五列,最后一个在第五行。

 输入

第一行包含两个整数R和C,中间用单个空格隔开。
接下来R行,每行C个字符,描述牧场地图。字符只有“#”或“.”两种。

输出

输出一个整数,表示草丛数。

样例输入
5 6
.#....
..#...
..#..#
...##.
.#....
样例输出
5

样例

裸的dfs搜索题,注意别忘了判重

 1 #include<iostream>
 2 using namespace std;
 3 int r,c;
 4 int dx[4]={-1,0,1,0};
 5 int dy[4]={0,1,0,-1};
 6 char a[101][101];
 7 bool v[101][101];
 8 int s;
 9 void dfs(int x,int y)
10 {
11     for(int i=0;i<4;i++)
12      {
13          int nx=x+dx[i],ny=y+dy[i];
14          if(nx>0&&nx<=r&&ny>0&&ny<=c&&a[nx][ny]==‘#‘&&!v[nx][ny])
15           {
16               v[nx][ny]=true;
17               dfs(nx,ny);
18          }
19      }
20 }
21 int main()
22 {
23     cin>>r>>c;
24     for(int i=1;i<=r;i++)
25      for(int j=1;j<=c;j++)
26       cin>>a[i][j];
27     for(int i=1;i<=r;i++)
28      for(int j=1;j<=c;j++)
29       if(a[i][j]==‘#‘&&!v[i][j])
30        {
31              v[i][j]=true;
32              dfs(i,j);
33              s++;
34        }
35     cout<<s;
36 } 

T18 肿瘤面积

描述

在一个正方形的灰度图片上,肿瘤是一块矩形的区域,肿瘤的边缘所在的像素点在图片中用0表示。其它肿瘤内和肿瘤外的点都用255表示。现在要求你编写一个程序,计算肿瘤内部的像素点的个数(不包括肿瘤边缘上的点)。已知肿瘤的边缘平行于图像的边缘。

输入

只有一个测试样例。第一行有一个整数n,表示正方形图像的边长。其后n行每行有n个整数,取值为0或255。整数之间用一个空格隔开。已知n不大于1000。

输出

输出一行,该行包含一个整数,为要求的肿瘤内的像素点的个数。

样例输入
5
255 255 255 255 255
255 0 0 0 255
255 0 255 0 255
255 0 0 0 255
255 255 255 255 255
样例输出
1

样例

首先搜索确定矩形框架,由题意得只有一个矩阵,所以按顺序搜到的第一个等于0的点一定是矩阵的左上角的顶点,假设为(i,j)。以(i,j)为基础,竖着在第j列搜,搜到一个点不是0或超出边界,即确定了矩阵左下角的顶点(x,j)。横着在第i行搜,搜到一个点不是0或超出边界,即确定了矩阵右上角的顶点(i,y),右下角的顶点为(x,y)。所以这个矩阵一共包含像素点(x-i+1)*(y-j+1)个,边缘有(x-i+y-j)*2个像素点,两个做差就是内部的像素点个数

 1 #include<iostream>
 2 using namespace std;
 3 int n,a[1001][1001];
 4 int main()
 5 {
 6     cin>>n;
 7     for(int i=1;i<=n;i++)
 8      for(int j=1;j<=n;j++)
 9       cin>>a[i][j];
10     for(int i=1;i<=n;i++)
11      for(int j=1;j<=n;j++)
12       if(!a[i][j])
13        {
14            int x=i,y=j;
15            while(x<=n)
16            {
17                x++;
18             if(a[x][j]) break;
19           }
20           x--;//前面x先++,在判断,所以break时x是已经超出边界或不符合条件的,所以要减1
21           while(y<=n)
22           {
23               y++;
24               if(a[i][y]) break;
25           }
26           y--;//减1的原理同上
27           int tot=(x-i+1)*(y-j+1);//总共的像素点
28           int bian=(x-i+y-j)*2;//边缘上的像素点
29           cout<<tot-bian;
30           return 0;
31        }
32 }

T19 肿瘤检测

描述

一张CT扫描的灰度图像可以用一个N*N(0 < N <= 100)的矩阵描述,矩阵上的每个点对应一个灰度值(整数),其取值范围是0-255。我们假设给定的图像中有且只有一个肿瘤。在图上监测肿瘤的方法如下:如果某个点对应的灰度值小于等于50,则这个点在肿瘤上,否则不在肿瘤上。我们把在肿瘤上的点的数目加起来,就得到了肿瘤在图上的面积。任何在肿瘤上的点,如果它是图像的边界或者它的上下左右四个相邻点中至少有一个是非肿瘤上的点,则该点称为肿瘤的边界点。肿瘤的边界点的个数称为肿瘤的周长。现在给定一个图像,要求计算其中的肿瘤的面积和周长。

输入

输入第一行包含一个正整数N(0 < N <= 100),表示图像的大小;接下来N行,每行包含图像的一行。图像的一行用N个整数表示(所有整数大于等于0,小于等于255),两个整数之间用一个空格隔开。

输出

输出只有一行,该行包含两个正整数,分别为给定图像中肿瘤的面积和周长,用一个空格分开。

样例输入
6
99 99 99 99 99 99
99 99 99 50 99 99
99 99 49 49 50 51
99 50 20 25 52 99
40 50 99 99 99 99
99 99 99 99 99 99
样例输出
9 8

样例

方法1:BFS,但是这道题题目描述有点问题,实际测试数据中有多个肿瘤,BFS只按一个肿瘤算只能拿4分。

方法2:枚举每一个元素,小于等于50则s+1,枚举完了s即为肿瘤面积,对于每一个小于等于50的元素判断是否是边界,是则c+1,最后c为周长,此种方法可以忽略有几个肿瘤的干扰,比BFS慢了2ms

#include<iostream>
using namespace std;
int n;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int a[101][101];
bool v[101][101];
int s,bian;
void dfs(int x,int y)
{
    s++;
    int ok=0;
    for(int i=0;i<4;i++)
     {
         int nx=x+dx[i],ny=y+dy[i];
         if(nx>0&&nx<=n&&ny>0&&ny<=n&&a[nx][ny]<=50)
          {
              if(!v[nx][ny])
            {
              v[nx][ny]=true;
                dfs(nx,ny);
            }
         }
        else ok=1;
     }
     if(ok) bian++;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      cin>>a[i][j];
    for(int i=1;i<=n;i++)
     for(int j=1;j<=n;j++)
      if(a[i][j]<=50&&!v[i][j])
       {
             v[i][j]=true;
             dfs(i,j);
       }
   cout<<s<<‘ ‘<<bian;
    return 0;
} 

1

#include<iostream>
using namespace std;
int main()
{
    int n,i,j,k,dx[]={1,-1,0,0},dy[]={0,0,1,-1},a[101][101],s=0,c=0;
    cin>>n;
    for(i=1;i<=n;i++)
     for(j=1;j<=n;j++)
      cin>>a[i][j];
    for(i=1;i<=n;i++)
     for(j=1;j<=n;j++)
        if(a[i][j]<=50)
         {
            s++;
            for(k=0;k<4;k++)
            if(a[i+dx[k]][j+dy[k]]>50||i==1||i==n||j==1||j==n)
            {
              c++;
              break;
            }
        }
   cout<<s<<" "<<c;
}

2

T20 反反复复

描述

Mo和Larry发明了一种信息加密方法。他们首先决定好列数,然后将信息(只包含字母)从上往下依次填入各列,并在末尾补充一些随机字母使其成为一个完整的字母矩阵。例如,若信息是“There‘s no place like home on a snowy night”并且有5列,Mo会写成:

t o i o yh p k n ne l e a ir a h s ge c o n hs e m o tn l e w x

注意Mo只会填入字母,且全部是小写形式。在这个例子中,Mo用字母“x”填充了信息使之成为一个完整的矩阵,当然他使用任何字母都是可以的。

Mo根据这个矩阵重写信息:首先从左到右写下第一行,然后从右到左写下第二行,再从左到右写下第三行……以此左右交替地从上到下写下各行字母,形成新的字符串。这样,例子中的信息就被加密为:toioynnkpheleaigshareconhtomesnlewx。

你的工作是帮助Larry从加密后的信息中还原出原始信息(包括填充的字母)。

输入

第一行包含一个整数(范围2到20),表示使用的列数。
第二行是一个长度不超过200的字符串。

输出

一行,即原始信息。

样例输入
5
toioynnkpheleaigshareconhtomesnlewx
样例输出
theresnoplacelikehomeonasnowynightx

样例

将加密后的字符串横着蛇形存储到数组中,再竖着一列一列的输出来

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 int n;
 5 char a[201][21],b[201];
 6 int main()
 7 {
 8     cin>>n;
 9     cin>>b;
10     int l=0,i=1,j=0;
11     int p=1;
12     while(l<strlen(b))//蛇形存储
13     {
14         if(p==1) j++;
15         else if(p==2)  j--;
16         if(j>n)
17         {
18             j=n;p=2;i++;
19         }
20         if(j<1)
21         {
22             j=1;p=1;i++;
23         }
24         a[i][j]=b[l];
25         l++;
26     }
27     for(int m=1;m<=n;m++)
28      for(int k=1;k<=i;k++)
29       cout<<a[k][m];
30 }

时间: 2024-10-22 13:20:19

noi题库(noi.openjudge.cn) 1.8编程基础之多维数组T11——T20的相关文章

noi寒假刷题之旅_ 1.8编程基础之多维数组(25题)

»1.8编程基础之多维数组(25题) 上次编辑的时候忘记保存了,前面几题就算了趴懒得 08:矩阵加法 #include<iostream> #define MAX 105 using namespace std; int table[MAX][MAX]; int main() { int n,m; cin>>n>>m; for(int i=0;i<n;++i)for(int j=0;j<m;++j)cin>>table[i][j]; int t;

noi题库(noi.openjudge.cn) 1.8编程基础之多维数组T1——T10

T01 矩阵交换行 描述 给定一个5*5的矩阵(数学上,一个r×c的矩阵是一个由r行c列元素排列成的矩形阵列),将第n行和第m行交换,输出交换后的结果. 输入 输入共6行,前5行为矩阵的每一行元素,元素与元素之间以一个空格分开.第6行包含两个整数m.n,以一个空格分开.(1 <= m,n <= 5) 输出 输出交换之后的矩阵,矩阵的每一行元素占一行,元素之间以一个空格分开. 样例输入 1 2 2 1 2 5 6 7 8 3 9 3 0 5 3 7 2 1 4 6 3 0 8 2 4 1 5 样

noi题库(noi.openjudge.cn) 1.8编程基础之多维数组T21——T25

T21 二维数组右上左下遍历 描述 给定一个row行col列的整数数组array,要求从array[0][0]元素开始,按从左上到右下的对角线顺序遍历整个数组. 输入 输入的第一行上有两个整数,依次为row和col.余下有row行,每行包含col个整数,构成一个二维整数数组.(注:输入的row和col保证0 < row < 100, 0 < col < 100) 输出 按遍历顺序输出每个整数.每个整数占一行. 样例输入 3 4 1 2 4 7 3 5 8 10 6 9 11 12

[NOI题库]1.1题解

今年NOIP居然"各有两道题目从NOI题库中抽取并在原题基础上改动后使用",不好好刷题怎么行. 这是第一篇题解文章,因为题目太水直接上代码了. 1.1编程基础之输入输出 01 Hello, World! 根据题意直接输出"Hello, World!"即可. #include <iostream> using namespace std; int main() { cout<<"Hello, World!"<<e

NOI题库 1768最大子矩阵 题解

NOI题库 1768最大子矩阵  题解 总时间限制: 1000ms 内存限制: 65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最大子矩阵是 9 2 -4 1 -1 8 这个子矩阵的大小是15. 输入   输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依

noi题库(noi.openjudge.cn) 1.7编程基础之字符串T21——T30

T21:单词替换 描述 输入一个字符串,以回车结束(字符串长度<=100).该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写.现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串. 输入 输入包括3行,第1行是包含多个单词的字符串 s;第2行是待替换的单词a(长度 <= 100);第3行是a将被替换的单词b(长度 <= 100). s, a, b 最前面和最后面都没有空格. 输出 输出只有 1 行,将s中所有单词a替换成b之后的字符串. 样例输入 You w

【NOI题库】9269:Big String超级字符串

传送门:http://noi.openjudge.cn/ch0207/9269/ //------------------------------------题目内容-------------------------------------- 9269:Big String超级字符串 总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 131072kB 描述 fish在无数次oi竞赛的狱炼之后,悟出一个真理,往往越容易的题目,陷阱越深.由此,fish创作了这道题目. f

[NOI题库]1.3编程基础之算术表达式与顺序执行 题解(一)

01 A+B问题 经典的A+B Problem——各大题库上的首题.读入$a,b$,输出$a+b$. #include <iostream> using namespace std; int main() { int a,b; cin>>a>>b; cout<<a+b<<endl; return 0; } 01.cpp 02 计算(a+b)*c的值 读入$a,b,c$,输出$c(a+b)$. #include <iostream> u

noi题库(noi.openjudge.cn) 1.5编程基础之循环控制T37——T38

T37 雇佣兵 描述 雇佣兵的体力最大值为M,初始体力值为0.战斗力为N.拥有X个能量元素. 当雇佣兵的体力值恰好为M时,才可以参加一个为期M天的战斗期,战斗期结束体力值将为0.在同一个战斗期内,雇佣兵每连续战斗n天,战斗力就会上升1点,n为当前战斗期开始时的战斗力. 一个战斗期结束后,雇佣兵需要用若干个能量元素使其体力恢复到最大值M,从而参加下一个战斗期.每个能量元素恢复的体力值不超过当前的战斗力.每个能量元素只能使用一次. 请问:雇佣兵的战斗力最大可以到达多少. 输入 一行包括三个整数M.N