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
样例输出
1
2
3
4
5
6
7
8
9
10
11
12

样例

先枚举第一行,向左下枚举,再枚举最后一列(除去右上角,因为第一行已经枚举过了)

 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 j=1;j<=m;j++)//枚举第一行
11     {
12         int i=1,k=j;//i:当前行,k:当前列
13         while(i<=n&&k>0)//不超边界
14         {
15             cout<<a[i][k]<<endl;
16             i++;k--;
17         }
18     }
19     for(int i=2;i<=n;i++)//最后一列,从第二行开始
20     {
21         int j=m,k=i;//j:当前列,k:当前行
22         while(k<=n&&j>0)//不超边界
23         {
24             cout<<a[k][j]<<endl;
25             k++;j--;
26         }
27     }
28 }

第一次枚举最后一列时从第一行开始的,0分。。。。。。

T22 神奇的幻方

描述

幻方是一个很神奇的N*N矩阵,它的每行、每列与对角线,加起来的数字和都是相同的。
我们可以通过以下方法构建一个幻方。(阶数为奇数)
1.第一个数字写在第一行的中间
2.下一个数字,都写在上一个数字的右上方:
    a.如果该数字在第一行,则下一个数字写在最后一行,列数为该数字的右一列
    b.如果该数字在最后一列,则下一个数字写在第一列,行数为该数字的上一行
    c.如果该数字在右上角,或者该数字的右上方已有数字,则下一个数字写在该数字的下方


输入

一个数字N(N<=20)

输出

按上方法构造的2N-1 * 2N-1的幻方

样例输入
3
样例输出
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

样例

类似于NOIP2015 Day1 T1,但这道题是2*n-1阶的

 1 #include<iostream>
 2 using namespace  std;
 3 int n,a[50][50];
 4 int main()
 5 {
 6     cin>>n;
 7     a[1][n]=1;
 8     int i=2,x=1,y=n;
 9     while(i<=(2*n-1)*(2*n-1))
10     {
11         if((x==1&&y==2*n-1)||a[x-1][y+1]) x+=1;
12         else if(x==1) x=2*n-1,y+=1;
13         else if(y==2*n-1) x-=1,y=1;
14         else x-=1,y+=1;
15         a[x][y]=i++;
16     }
17     for(int k=1;k<=2*n-1;k++)
18      {
19          for(int l=1;l<=2*n-1;l++)
20          cout<<a[k][l]<<‘ ‘;
21          cout<<endl;
22      }
23 } 

T23 二维数组回形遍历

描述

给定一个row行col列的整数数组array,要求从array[0][0]元素开始,按回形从外向内顺时针顺序遍历整个数组。如图所示:

输入

输入的第一行上有两个整数,依次为row和col。
余下有row行,每行包含col个整数,构成一个二维整数数组。
(注:输入的row和col保证0 < row < 100, 0 < col < 100)

输出

按遍历顺序输出每个整数。每个整数占一行。

样例输入
4 4
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
样例输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

样例

递归遍历即可,一定要注意一个格子只能走一遍以及判断是否输出了所有数,不然会递归死循环

 1 #include<iostream>
 2 using namespace std;
 3 int n,m,a[101][101];
 4 bool v[101][101];
 5 bool ok;
 6 bool judge()//判断是否已经输出了所有的数
 7 {
 8     for(int i=1;i<=n;i++)
 9      for(int j=1;j<=m;j++)
10       if(!v[i][j]) return false;
11     return true;
12 }
13 //R向右 ,D向下,L向左,U向上
14 void dfs(int x,int y,char p)//x:当前行,y:当前列,p判断向哪儿走
15 {
16     if(ok) return;//在judge之前先判断是否已经输出了所有点,防止输出完递归回退时多次执行judge函数,浪费时间
17     ok=judge();
18     if(p==‘R‘)//可以向右走
19     {
20         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])//不超边界且没有被遍历
21         {
22             cout<<a[x][y]<<endl;
23             v[x][y]=true;
24             dfs(x,y+1,‘R‘);//继续向右走
25         }
26         else p=‘D‘,dfs(x+1,y-1,‘D‘);//转为向下走,当执行这个语句时,y已经超出了边界,所以要减1,向下走x+1
27     }
28     else if(p==‘D‘)
29     {
30         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])
31         {
32             cout<<a[x][y]<<endl;
33             v[x][y]=true;
34             dfs(x+1,y,‘D‘);
35         }
36         else p=‘L‘,dfs(x-1,y-1,‘L‘);
37     }
38     else if(p==‘L‘)
39     {
40         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])
41         {
42             cout<<a[x][y]<<endl;
43             v[x][y]=true;
44             dfs(x,y-1,‘L‘);
45         }
46         else p=‘U‘,dfs(x-1,y+1,‘U‘);
47     }
48     else if(p==‘U‘)
49     {
50         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])
51         {
52             cout<<a[x][y]<<endl;
53             v[x][y]=true;
54             dfs(x-1,y,‘U‘);
55         }
56         else p=‘R‘,dfs(x+1,y+1,‘R‘);
57     }
58 }
59 int main()
60 {
61     cin>>n>>m;
62     for(int i=1;i<=n;i++)
63      for(int j=1;j<=m;j++)
64       cin>>a[i][j];
65     dfs(1,1,‘R‘);
66 }

T24 蛇形填充数组

描述

用数字1,2,3,4,...,n*n这n2个数蛇形填充规模为n*n的方阵。

蛇形填充方法为:

对于每一条左下-右上的斜线,从左上到右下依次编号1,2,...,2n-1;按编号从小到大的顺序,将数字从小到大填入各条斜线,其中编号为奇数的从左下向右上填写,编号为偶数的从右上到左下填写。

比如n=4时,方阵填充为如下形式:

1  2  6  7
3  5  8  13
4  9  12 14
10 11 15 16

输入

输入一个不大于10的正整数n,表示方阵的行数。

输出

输出该方阵,相邻两个元素之间用单个空格间隔。

注意处理边界情况。

①:超出矩阵上边界,此时位置坐标已经到①出,列与拐弯后的位置的列相等,行少了1,所以行+1,列不变

②:超出矩阵右边界,此时位置坐标已经到②出,行与拐弯后的位置的行少了2行,列多了一列,所以行+2,列-1

③:即超出上边界,又超出右边界,此时位置到③处,我们可以手算一下,若先执行①,再执行②,会到达A处;先执行②,再执行①,会到达B处,而拐弯后的目标位置为B处,所以在程序中,要先判断②的情况,在判断①的情况。

当然为了避免③的情况,也可以另写一个语句直接判断

如果不是边界,直接行减1,列加1

当向左下方填充时,情况类似,就不再写了

 1 #include<iostream>
 2 using namespace std;
 3 int n,a[11][11];
 4 bool ok;
 5 int main()
 6 {
 7     cin>>n;
 8     int s=0,p=1;
 9     int x=1,y=1;
10     while(s<n*n)//填充,具体解释看上面的题解
11     {
12         while(p%2==0&&s<n*n)
13         {
14             ok=false;
15             s++;
16             a[x][y]=s;
17             x++;y--;
18             if(x>n) x--,y+=2,ok=true;
19             if(y<1) y++,ok=true;
20             if(ok) p++;
21         }
22         while(p%2==1&&s<n*n)
23         {
24             ok=false;
25             s++;
26             a[x][y]=s;
27             x--;y++;
28             if(y>n) x+=2,y--,ok=true;
29             if(x<1) x++,ok=true;
30             if(ok) p++;
31         }
32     }
33     for(int i=1;i<=n;i++)
34      {
35          for(int j=1;j<=n;j++)
36           cout<<a[i][j]<<‘ ‘;
37          cout<<endl;
38      }
39 } 

一开始没考虑③的情况,先判断的①,在判断的②,导致对角线拐弯时错行

T25 螺旋加密

描述

Chip和Dale发明了一种文本信息加密技术。他们事先秘密约定好矩阵的行数和列数。接着,将字符按如下方式编码:

1. 所有文本只包含大写字母和空格。

2. 每个字符均赋予一个数值:空格=0,A=1,B=2,……,Y=25,Z=26。

按照下图所示的方式,将每个字符对应数值的5位二进制数依次填入矩阵。最后用0将矩阵补充完整。例如,对于信息“ACM”,行列数均为4时,矩阵将被填充为:

将矩阵中的数字按行连起来形成数字串,完成加密。例子中的信息最终会被加密为:0000110100101100。

输入

一行。首先是两个整数R(1≤R≤20)和C(1≤C≤20),表示行数和列数。之后是一个只包含大写字母和空格的字符串。字符串的长度≤(R*C)/5。R和C之间以及C和字符串之间均用单个空格隔开。

输出

一行,为加密后的二进制串。注意你可能需要用0将矩阵补充完整。

先将字符串按要求转化为二进制数字,然后再用类似T23二维数组回形遍历的方法把数字存到矩阵里,最后按顺序输出。这种方法虽然麻烦点儿,但比较快,用时0ms

注意数据的读入方式,为了防止读入多余的空格或少读空格,可以将一整行当字符串用gets读进去,再找空格分开。也可以多输入一个getchar()语句。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 int n,m,a[101][101];
 6 char s[100];
 7 int ss[1000];
 8 bool v[101][101];
 9 int sum;
10 //R向右 ,D向下,L向左,U向上
11 void dfs(int x,int y,char p)//x:当前行,y:当前列,p判断向哪儿走
12 {
13     if(sum==n*m) return;
14     if(p==‘R‘)//可以向右走
15     {
16         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])//不超边界且没有被填充
17         {
18             a[x][y]=ss[++sum];
19             v[x][y]=true;
20             dfs(x,y+1,‘R‘);//继续向右走
21         }
22         else p=‘D‘,dfs(x+1,y-1,‘D‘);//转为向下走,当执行这个语句时,y已经超出了边界,所以要减1,向下走x+1
23     }
24     else if(p==‘D‘)
25     {
26         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])
27         {
28             a[x][y]=ss[++sum];
29             v[x][y]=true;
30             dfs(x+1,y,‘D‘);
31         }
32         else p=‘L‘,dfs(x-1,y-1,‘L‘);
33     }
34     else if(p==‘L‘)
35     {
36         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])
37         {
38             a[x][y]=ss[++sum];
39             v[x][y]=true;
40             dfs(x,y-1,‘L‘);
41         }
42         else p=‘U‘,dfs(x-1,y+1,‘U‘);
43     }
44     else if(p==‘U‘)
45     {
46         if(x>0&&x<=n&&y>0&&y<=m&&!v[x][y])
47         {
48             a[x][y]=ss[++sum];
49             v[x][y]=true;
50             dfs(x-1,y,‘U‘);
51         }
52         else p=‘R‘,dfs(x+1,y+1,‘R‘);
53     }
54 }
55 int main()
56 {
57     gets(s);
58     int i;
59     for(i=0;i<strlen(s);i++)//取出行 n
60      {
61          if(s[i]!=‘ ‘) n=n*10+s[i]-‘0‘;
62          else break;
63      }
64     int j;
65     for(j=i+1;j<strlen(s);j++)//取出列 m
66     {
67         if(s[j]!=‘ ‘) m=m*10+s[j]-‘0‘;
68         else break;
69     }
70     int l=0;
71     for(int k=j+1;k<strlen(s);k++) //将字符串转化为二进制
72      {
73          if(s[k]==‘ ‘)//空格的情况时5个0
74          for(int u=1;u<=5;u++)  ss[++l]=0;
75          else
76          {
77              l+=5;//倒着填二进制数
78             int p=s[k]-64,w=0;
79              while(p)
80              {
81                  ss[l]=p%2;
82                  p/=2;
83                  l--;
84             }
85             while(l%5) ss[l]=0,l--;//二进制位数有可能不足5位
86             l+=5;//前面倒着填的再加回去
87          }
88      }
89      for(int k=l+1;k<=n*m;k++)
90       ss[k]=0;//用0将矩阵补充完整
91     dfs(1,1,‘R‘);
92     for(int p=1;p<=n;p++)
93      for(int k=1;k<=m;k++)
94       cout<<a[p][k];
95 }

下附简短代码,用时1ms

精简之处1:cin、getchar()与getline()的使用省去上面用gets读入在分离的过程

精简之处2:打表提前打出26个英文字符的二进制,利用c++自带的substr函数省去循环5次存储五位二进制的过程

精简之处3:将二进制数存到矩阵中时,以矩阵的一圈为单位,依次以(1,1)、(2,2)、(3,3)等为起点,用while一圈一圈的存储,而不是dfs

精简之处4:题目要求,用0将矩阵补充完整,全局变量定义数组初始值即为0,可以不用管

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,l,c,x,y,t,a[105][105];
 4 string s,ss,q="0000100010000110010000101001100011101000010010101001011011000110101110011111000010001100101001110100101011011010111110001100111010";
 5 int main()
 6 {
 7     cin>>n>>m;
 8     getchar();
 9     getline(cin,s);
10     l=s.size();
11     for(int k=0;k<l;k++)
12        if(s[k]==‘ ‘)  ss+="00000";
13     else ss+=q.substr(5*(s[k]-‘A‘),5);
14     while(t<5*l)
15     {
16        c++;x=c;y=c;
17        while(y+c<=m+1&&t<5*l){a[x][y]=ss[++t-1]-‘0‘;y++;}y--;x++;
18        while(x+c<=n+1&&t<5*l){a[x][y]=ss[++t-1]-‘0‘;x++;}x--;y--;
19        while(y>=c&&t<5*l){a[x][y]=ss[++t-1]-‘0‘;y--;}y++;x--;
20        while(x>c&&t<5*l){a[x][y]=ss[++t-1]-‘0‘;x--;}
21     }
22     for(int i=1;i<=n;i++)
23       for(int j=1;j<=m;j++)
24          cout<<a[i][j];
25 return 0;
26 }

2

时间: 2024-09-29 18:34:02

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

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编程基础之多维数组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

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题库]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