太阳能电池板网格优化

题意:给定 \(n \times n\)\(01\) 矩阵 \(A\)\(B\),可以进行两种操作:

  • \(\text{row}(i)\) 表示将 \(A\) 的第 \(i\) 行循环左移一位,如:

\[\begin{bmatrix} 1 & 1 & 0 \\ \color{red}{1} & \color{green}{0} & \color{blue}{1} \\ 1 & 1 & 0 \end{bmatrix} \to \begin{bmatrix} 1 & 1 & 0 \\ \color{green}{0} & \color{blue}{1} & \color{red}{1} \\ 1 & 1 & 0 \end{bmatrix} \]

  • \(\text{column}(i)\) 表示将 \(A\) 的第 \(i\) 列循环下移一位后,反转第 \(i\) 列最上面的一位,如:

\[\begin{bmatrix} 1 & \color{red}{1} & 0 \\ 1 & \color{green}{0} & 1 \\ 1 & \color{blue}{1} & 0 \end{bmatrix} \to \begin{bmatrix} 1 & \color{blue}{0} & 0 \\ 1 & \color{red}{1} & 1 \\ 1 & \color{green}{0} & 0 \end{bmatrix} \]

你要在 \(1000\) 次操作内将 \(A\) 变成 \(B\)\(n \leq 20\)


下面定义一些基本函数:

  • \(\text{revcolumn}(i)\):执行 \(n\)\(\text{column}(i)\),可以反转第 \(i\) 列。

  • \(\text{xorrow}(i)\):第 \(i\) 行的所有数异或和。


考虑我们如何构造一个特定的列,假设矩阵为:

\[\begin{bmatrix} 1 & 1 & 0 \\ 1 & 0 & 1 \\ 1 & 1 & 0 \end{bmatrix} \]

我们要构造一列:

\[\begin{bmatrix} 1 \\ 0 \\ 0 \end{bmatrix} \]

  • 先将最后一列中符合要求的行左移一位

\[\begin{bmatrix} 1 & 1 & 0 \\ 1 & 0 & 1 \\ \color{red}{1} & \color{red}{0} & \color{red}{1} \end{bmatrix} \]

  • 反转最后一列:

\[\begin{bmatrix} 1 & 1 & \color{red}{1} \\ 1 & 0 & \color{red}{0} \\ 1 & 0 & \color{red}{0} \end{bmatrix} \]

  • 左移第一步中未左移的行

\[\begin{bmatrix} \color{red}{1} & \color{red}{1} & \color{red}{1} \\ \color{red}{0} & \color{red}{0} & \color{red}{1} \\ 1 & 0 & 0 \end{bmatrix} \]

容易发现此时矩阵的第 \(n-1\) 列满足要求,且过程中会改变所有的 \(\text{xorrow}(i)\)

我们可以通过这种方法修改前 \(n-1\) 列,对于最后一列我们算出需要的 \(\text{xorrow}\)

问题变为对每一行获得需要的奇偶性,分为以下步骤:

  • 清空第 \(n\)

使用刚才的做法即可,

  • 清空第 \(n\)

找到第 \(n\) 行的 \(1\),使用 \(\text{row}\) 操作将 \(1\) 放到 \((n,n)\),然后转第 \(n\) 列。

  • 反转第 \(n\)

使用 \(\text{revcolumn}\) 即可

  • 改变第 \(1\) 行到第 \(n-1\) 行的奇偶性

依次考虑第 \(n-1\) 行到第 \(1\) 行,是需要 \(0\) 还是需要 \(1\),如果需要 \(1\) 则搬 \(0\)

  • 改变第 \(n\) 行的奇偶性

此时的第 \(n\) 行必然有一个 \(1\)

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
bool a[30][30],b[30][30],tar[30];
struct Node{
	string op;
	int num;
};
vector<Node> ans;
bool tmp[30];
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			char ch;
			cin>>ch;
			if(ch=='1'){
				a[i][j]=true;
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			char ch;
			cin>>ch;
			if(ch=='1'){
				b[i][j]=true;
				tar[i]=!tar[i];
			}
		}
		if(n%2==0){
			tar[i]=!tar[i];
		}
	}
	for(int i=1;i<=n;i++){
		if(a[i][1]==false){
			ans.push_back((Node){"row",i});
			for(int j=1;j<n;j++){
				a[i][j]=a[i][j+1];
			}
			a[i][n]=false;
			tmp[i]=true;
		}
	}
	for(int i=1;i<=n;i++){
		ans.push_back((Node){"column",1});
		a[i][1]=!a[i][1];
	}
	for(int i=1;i<=n;i++){
		if(tmp[i]==false){
			ans.push_back((Node){"row",i});
			for(int j=1;j<n;j++){
				a[i][j]=a[i][j+1];
			}
			a[i][n]=false;
		}
	}
	int cnt_1=0;
	for(int i=1;i<=n;i++){
		if(a[n][i]==true){
			cnt_1++;
		}
	}
	while(cnt_1){
		while(a[n][n]!=true){
			ans.push_back((Node){"row",n});
			bool tmp_num=a[n][1];
			for(int i=1;i<n;i++){
				a[n][i]=a[n][i+1];
			}
			a[n][n]=tmp_num;
		}
		ans.push_back((Node){"column",n});
		a[n][n]=false;
		cnt_1--;
	}
	for(int i=1;i<=n;i++){
		ans.push_back((Node){"column",n});
		a[i][n]=true;
	}
	cnt_1=0;
	for(int i=1;i<n;i++){
		bool tmp=false; 
		for(int j=1;j<n;j++){
			if(a[i][j]){
				tmp=!tmp;
			}
		}
		if(tmp!=tar[i]){
			cnt_1++;
		}
	}
	if(cnt_1%2==tar[n]){
		ans.push_back((Node){"column",n});
		a[1][n]=false;
	}
	for(int i=n-1;i>=1;i--){
		bool tmp=false; 
		for(int j=1;j<n;j++){
			if(a[i][j]){
				tmp=!tmp;
			}
		}
		if(tmp!=tar[i]){
			cnt_1++;
			ans.push_back((Node){"row",n});
			bool tmp_num=a[n][1];
			for(int j=1;j<n;j++){
				a[n][j]=a[n][j+1];
			}
			a[n][n]=tmp_num;
		}
		ans.push_back((Node){"column",n});
		bool tmp_num=a[n][n];
		for(int j=n-1;j>=1;j--){
			a[j+1][n]=a[j][n];
		}
		a[1][n]=!tmp_num;
	}
	for(int i=1;i<n;i++){
		for(int j=1;j<=n;j++){
			if(a[j][n]==b[j][i]){
				ans.push_back((Node){"row",j});
				bool tmp_num=a[j][1];
				for(int k=1;k<n;k++){
					a[j][k]=a[j][k+1];
				}
				a[j][n]=tmp_num;
				tmp[j]=true;
			}
			else{
				tmp[j]=false;
			}
		}
		for(int j=1;j<=n;j++){
			ans.push_back((Node){"column",n});
			a[j][n]=!a[j][n];
		}
		for(int j=1;j<=n;j++){
			if(tmp[j]==false){
				ans.push_back((Node){"row",j});
				bool tmp_num=a[j][1];
				for(int k=1;k<n;k++){
					a[j][k]=a[j][k+1];
				}
				a[j][n]=tmp_num;
			}
		}
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++){
		cout<<ans[i].op<<" "<<ans[i].num<<endl;
	}
	return 0;
}
posted @ 2026-07-19 18:00  Oken喵~  阅读(11)  评论(1)    收藏  举报