打卡第二十二天

1.方块转换

问题描述

一块N x N(1=<N<=10)正方形的黑白瓦片的图案要被转换成新的正方形图案。

写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式:

#1:转90度:图案按顺时针转90度。

#2:转180度:图案按顺时针转180度。

#3:转270度:图案按顺时针转270度。

#4:反射:图案在水平方向翻转(形成原图案的镜像)。

#5:组合:图案在水平方向翻转,然后按照#1-#3之一转换。

#6:不改变:原图案不改变。

#7:无效转换:无法用以上方法得到新图案。

如果有多种可用的转换方法,请选择序号最小的那个。

比如:

转换前:

@-@


@@-

转换后:

@-@

@--

--@

这种转换采取#1(按顺时针转90度)即可。

注意:图案中的字符"@"和"-"在转90度后,还是"@"和"-"。不要认为"-"转90度后变成"|"。

输入说明

第一行: 单独的一个整数N。

第二行到第N+1行: N行,每行N个字符(不是'@'就是'-');这是转换前的正方形。

第N+2行到第2*N+1行: N行,每行N个字符(不是'@'就是'-');这是转换后的正方形。

输出说明

单独的一行包括1到7之间的一个数字(在上文已描述)表明需要将转换前的正方形变为转换后的正方形的转换方法。

个人总结

1.直接用 vector<string> 来表示正方形图案,这样可以直接使用 == 或自定义的 isEqual 函数比较

2.旋转90度:new[j][N-1-i] = old[i][j]

3.square[i][j] ,i代表字符串的索引,j代表字符串中的字符索引。vector<string> 定义的数组天然是一个二维数组,因为字符串(string)本身也是一个字符数组

cpp 复制代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int n;
//顺时针旋转90度
vector<string> shun90(vector<string> square){
	vector<string> res(n,string(n,' ')); //初始化n*n的空矩阵,存放旋转后的字符
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[j][n-1-i]=square[i][j];
		}
	}
	return res;
}
//镜像
vector<string> reflect(vector<string> square){
	vector<string> res(n,string(n,' '));
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			res[i][n-1-j]=square[i][j];
		}
	}
	return res;
}
//检查两个矩阵是否相等
bool isEqual(vector<string> a,vector<string> b){
	for(int i=0;i<n;i++){
		if(a[i]!=b[i]) return false;
	}
	return true;
}

int main(){
	cin>>n;
	vector<string> before(n),after(n);
	for(int i=0;i<n;i++) cin>>before[i];
	for(int i=0;i<n;i++) cin>>after[i];
	vector<string> r90=shun90(before);
	vector<string> r180=shun90(r90);
	vector<string> r270=shun90(r180);
	vector<string> fan=reflect(before);
	
	if(isEqual(r90,after)) cout<<1<<endl;
	else if(isEqual(r180,after)) cout<<2<<endl;
	else if(isEqual(r270,after)) cout<<3<<endl;
	else if(isEqual(fan,after)) cout<<4<<endl;
	else if(isEqual(shun90(fan), after) || 
               isEqual(shun90(shun90(fan)), after) || 
               isEqual(shun90(shun90(shun90(fan))), after))
		cout<<5<<endl;
	else if(isEqual(before,after)) cout<<6<<endl;
	else cout<<7<<endl;
		
	return 0;
}

2.螺旋方阵

问题描述

明明在上学的时候,参加数学兴趣班。在班上,老师介绍了一种非常有趣的方阵,称之为螺旋方阵。该方阵一共由n×n个正整数构成(我们称之为n阶螺旋方阵),即共有n行n列。

方阵中的数字从1开始递增,数字的排序规则是从左上角出发由1开始排序,并按顺时针方向旋进,即先排最外面的一圈,然后排里面的一圈,以此类推,直到排到最后一个数为止。

例如一个4阶的螺旋方阵,一共有4×4=16个正整数构成,数字从1递增到16,最后排出来的方阵如下:

1 2 3 4

12 13 14 5

11 16 15 6

10 9 8 7

明明回家后想自己动手构造这样的螺旋方阵。他从n=1开始构造,但是他发现当n越来越大时,螺旋方阵的复杂性就越高,然后构造出来的方阵就越容易出错。为了降低构造方阵的出错率,提高构造速度,明明就求助于你,请你帮他写一个程序,来构造螺旋方阵。 明明的问题可以归结为:给你一个正整数n,请你按题目描述中所述的方法,构造出n阶的螺旋方阵。

输入说明

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个正整数n(1≤n≤10),即所要构造的螺旋方阵的阶数。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个n阶的螺旋方阵,方阵中的数字用一个空格隔开,具体形式请参考输出样例。每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有空行。 注:通常,显示屏为标准输出设备。

个人总结

定义 top, bottom, left, right 四个边界,每走完一边就收缩。

边界条件while (num <= n * n) 是总控制。在每一个 for 循环里也加上 num <= n * n 是为了防止在 n 为奇数最后填充中心点时,由于边界已经交错而产生多余的覆盖。

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
	int n;
	while(cin>>n){
		int a[10][10]={0};
		//定义边界
		int top=0,bottom=n-1;
        int left=0,right=n-1;
		int num=1;
		
		while(num<=n*n){
			for(int j=left;j<=right&&num<=n*n;j++){
				a[top][j]=num++;
			} 
			top++;//顶部填完,往下移
			for(int i=top;i<=bottom&&num<=n*n;i++){
				a[i][right]=num++;
			}
			right--; //最右边填完,左移
			for(int j=right;j>=left&&num<=n*n;j--){
				a[bottom][j]=num++;
			}
			bottom--;//底部填完,上移
			for(int i=bottom;i>=top&&num<=n*n;i--){
				a[i][left]=num++;
			}
			left++;
		}
		//输出	
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				if(j!=0) cout<<" ";
				cout<<a[i][j];
			}
			cout<<endl;
		}
		cout<<endl;
	}
	return 0;
}

3.阵列

问题描述

明明在上学的时候,参加数学兴趣班。在班上,老师介绍了一种非常有趣的阵列。

该阵列由n个正整数构成,阵列中的数字从1开始递增,数字的排序规则是从1开始由中间逆时针向外转出,2出现在1的下面,然后直至输出n为止。

例如当n=5的时候,阵列如下:

5

1 4

2 3

当n=9时,阵列如下:

7 6 5

8 1 4

9 2 3

当n=10时,阵列如下:

7 6 5

8 1 4

9 2 3

10

明明回家后想自己动手构造这样的阵列。他从n=1开始构造,但是他发现当n越来越大时,阵列的复杂性就越高,然后构造出来的阵列就越容易出错。为了降低构造阵列的出错率,提高构造速度,明明就求助于你,请你帮他写一个程序,来构造这样的阵列。

明明的问题可以归结为:给你一个正整数n,请你按题目描述中所述的方法,构造出阵列。

输入说明

你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅占一行,每行仅有一个正整数n(1≤n≤99),即所要构造的阵列的大小。每组测试数据与其后一组测试数据之间没有任何空行,第一组测试数据前面以及最后一组测试数据后面也都没有任何空行。

输出说明

对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为一个大小为n的阵列,阵列中的数字用一个空格隔开,具体形式请参考输出样例: 当n为个位数时,输出的每个数占1位,当n为两位数时,两位数所在的列输出的每个数占2位(不足2位的左边补空格)。 每组运算结果与其后一组运算结果之间有一个空行,最后一组运算结果之后没有任何空行。 注:通常,显示屏为标准输出设备。

个人总结

1.方向数组:

在 C++ 二维数组 a[x][y] 中:

  • x (行)+1 是向下,-1 是向上。

  • y (列)+1 是向右,-1 是向左。

  • 对应的顺序:上、下、左、右

    int dx[] = {-1, 1, 0, 0};

    int dy[] = { 0, 0, -1, 1};

2.螺旋矩阵模拟:

  1. 按步长模拟(Step-based) :找步数规律(1, 1, 2, 2...)。适合由内向外扩散的螺旋

  2. 按边界/碰撞模拟(State-checking) :走一步看一步(能转就转,不能转直走/撞墙了就转)。适合由外向内收缩的螺旋

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
 
int main() {
	int n;
	bool fst_case = true;
	while (cin >> n) {
		int a[20][20] = {0};
		// 标记每一列的位数,也可以用来判断一列是否为空
		int clen[20] = {0};
		// 记录每一行是否有数字(非0即有效行)
		int rlen[20] = {0};
 
		// 方向数组:下,右,上,左
		int dx[] = {1, 0, -1, 0};
		int dy[] = {0, 1, 0, -1};
 
		a[10][10] = 1;
		clen[10] = 1;
		rlen[10] = 1;
 
		// 填入后续
		int step = 1; //步长
		int dir = 0; //当前方向
		int cur = 2; //当前要填的数字
		int x = 10, y = 10;//当前坐标
		while (cur <= n) {
			for (int j = 0; j < 2; j++) { //每两个方向为一组
				for (int i = 0; i < step; i++) { //走几步
					if (cur > n) break; // 填完了,直接退出
 
					// 来到新坐标并填写
					x += dx[dir];
					y += dy[dir];
					a[x][y] = cur;
 
					// 记录宽度
					if (cur < 10) {
						clen[y] = 1;
						rlen[x] = 1;
					} else {
						clen[y] = 2;
						rlen[x] = 2;
					}
 
					// 更新数字
					cur++;
				}
				// 转向
				dir = (dir + 1) % 4;
			}
			// 更新步长
			step++;
		}
 
		// 输出
		// 除第一组输出外其他组先输出一个空行
		if (fst_case) {
			fst_case = false;
		} else {
			cout << "\n";
		}
 
		// 找到第一个开始的列,便于之后判断是否先输出空格
		int fst_col,fst_row;
		for (int i = 0; i < 20; i++) {
			if (clen[i] != 0) {
				fst_col = i;
				break;
			}
		}
		for (int i = 0; i < 20; i++) {
			if (rlen[i] != 0) {
				fst_row = i;
				break;
			}
		}

		// 逐个输出
		for (x = fst_row; rlen[x] != 0; x++) {
			for (y = fst_col; clen[y] != 0; y++) {
				// 行末尾连续空白:不输出,直接跳过
				if (a[x][y] == 0 && a[x][y+1] == 0) {
					continue;
				}
							
				//非第一列需要先输出空格
				if (y != fst_col) cout << " ";
 
				// 按照列宽度输出
				if (a[x][y] == 0) {//没数字,但也要占位置,保证矩阵对齐整齐
					cout << setw(clen[y]) << " ";
				} else {
					cout << setw(clen[y]) << a[x][y];
				}
			}
			cout << "\n";
		}
 
	}
 
	return 0;
}

单词打卡

英语翻译

Federated learning is a distributed machine learning approach that aims to train models while preserving user data privacy. In traditional machine learning methods, data is usually centralized on servers for training. However, in many real-world scenarios, data is private and sensitive, making it difficult to share directly. Federated learning addresses this problem by training models locally on devices and only uploading model parameters or gradient information to a central server. In this way, collaborative learning can be achieved without exposing raw data. Federated learning has attracted increasing attention in fields such as mobile computing, medical data analysis, and financial risk control.

联邦学习是一个分布式机器学习方式,目标是在保护用户数据隐私的同时训练模型。在传统的机器学习方法中,数据通常主要服务于训练。但是,在许多现实世界的场景中,数据是私有的和敏感的,这使得直接共享变得困难。联邦学习通过在设备上局部训练模型以及只上传模型参数或梯度数据给中心服务器。通过这种方式,协作学习可以不用暴露原始数据就能实现。联邦学习已经吸引了越来越多的注意力在一些领域比如远程计算,医学数据分析和财经风险控制。

相关推荐
pu_taoc2 小时前
理解 lock_guard, unique_lock 与 shared_lock 的设计哲学与应用场景
开发语言·c++·算法
XW01059992 小时前
6-函数-1 使用函数求特殊a串数列和
数据结构·python·算法
myloveasuka2 小时前
红黑树、红黑规则、添加节点处理方案
开发语言·算法
沉鱼.442 小时前
枚举问题集
java·数据结构·算法
2301_810160952 小时前
C++中的访问者模式高级应用
开发语言·c++·算法
郝学胜-神的一滴2 小时前
走进计算机图形学的浪漫宇宙 | GAMES101 开篇课程全解析
c++·算法·图形渲染·计算机图形学
没头脑的男大2 小时前
灵神,2x树的层序遍历,102,103,513
算法
m0_518019482 小时前
C++中的享元模式
开发语言·c++·算法
我带你来这儿就是为了告诉你我2 小时前
C++23新特性前瞻
开发语言·c++·算法