专栏文章

题解:B4226 [常州市赛 2024] 密码

B4226题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@mip9prh2
此快照首次捕获于
2025/12/03 08:27
3 个月前
此快照最后确认于
2025/12/03 08:27
3 个月前
查看原文
题目:https://www.luogu.com.cn/problem/B4226

一道经典的模版题

如果新手们看不懂大佬的方法推荐这个。

思路:

先把输入的矩阵转化为一个字符串,再把字符串转化为另一个矩阵。

处理字符组

我采用的是数学的方法,观察到每一斜排的横坐标加纵坐标为定值,所以可再主函数中采用直接循环的方法处理字符组。

代码如下:

CPP
for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++){
			if(i+j<=n+1){//左上部分(包括最中间)
				if((i+j)%2==0)
					b[sum(i+j-2)+j]=a[i][j];
				else
					b[sum(i+j-2)+i]=a[i][j];
			}
			else{//右下部分
				if((i+j)%2==0)
					b[n*n-sum(2*n-i-j)-n+j]=a[i][j];
				else
					b[n*n-sum(2*n-i-j)-n+i]=a[i][j];
			}
		}

然后处理转换后的矩阵

这次采用模拟的方法,其中m是转换的序数,flag是方向指针,visit是访问数组。

看代码吧

CPP
int flag=1;
int x=1,y=1,n,m=1;
bool visit[501][501];
char a[501][501],b[501*501],c[501][501];//矩阵与字符组
void change(){
	c[x][y]=b[m];//赋值
	switch(flag){
		case 1:
			if(visit[x+1][y]||x==n){
				flag++;
				y++;
			}
			else{
				x++;
			}
			break;
		case 2:
			if(visit[x][y+1]||y==n){
				flag++;
				x--;
			}
			else{
				y++;
			}
			break;
		case 3:
			if(visit[x-1][y]||x==1){
				flag++;
				y--;
			}
			else{
				x--;
			}
			break;
		case 4:
			if(visit[x][y-1]||y==1){
				flag=1;
				x++;
			}
			else{
				y--;
			}
			break;
	}
	visit[x][y]=1;//将(x,y)设为访问过
	m++;//轮到下一个
	return; 
}
但是,注意:一次自定义只能复制一次。

最后放一下完整 AC 代码:

CPP
#include<bits/stdc++.h>//万能头不解释
using namespace std;
int flag=1;
int x=1,y=1,n,m=1;
bool visit[501][501];
char a[501][501],b[501*501],c[501][501];//矩阵与字符组
void change(){
	c[x][y]=b[m];
	switch(flag){
		case 1:
			if(visit[x+1][y]||x==n){
				flag++;
				y++;
			}
			else{
				x++;
			}
			break;
		case 2:
			if(visit[x][y+1]||y==n){
				flag++;
				x--;
			}
			else{
				y++;
			}
			break;
		case 3:
			if(visit[x-1][y]||x==1){
				flag++;
				y--;
			}
			else{
				x--;
			}
			break;
		case 4:
			if(visit[x][y-1]||y==1){
				flag=1;
				x++;
			}
			else{
				y--;
			}
			break;
	}
	visit[x][y]=1;//将(x,y)设为访问过
	m++;//轮到下一个
	return; 
}
int sum(int number){
	return number*(number+1)/2;
}
int main(){
	visit[1][1]=1;//赋初始值
	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(i+j<=n+1){
				if((i+j)%2==0)
					b[sum(i+j-2)+j]=a[i][j];
				else
					b[sum(i+j-2)+i]=a[i][j];
			}
			else{
				if((i+j)%2==0)
					b[n*n-sum(2*n-i-j)-n+j]=a[i][j];
				else
					b[n*n-sum(2*n-i-j)-n+i]=a[i][j];
			}
		}
	for(int i=1;i<=n*n;i++)
			change();//记得是n²不是n!!!
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			cout<<c[j][i];//输出
		cout<<"\n";
	}
	return 0;
}
如果你看懂了以上全部内容,AC 就离你不远了。

评论

2 条评论,欢迎与作者交流。

正在加载评论...