问题描述:有m*n枚金币在桌面上排列成一个m行n列的金币阵列。每一枚金币或正面朝上,或背面朝上。用数字表示金币状态,0表示正面朝上,1表示背面朝上。
金币阵列游戏的规则是:
(1)每次将任一行金币翻过来放在原来的位置上。
(2)每次可以任选2列,交换这2列金币的位置。
任务:给定金币的初始状态和目标状态,编程计算按金币游戏规则,将金币排列从初始状态变换到目标状态所需的最少变换次数。
这题我一开始想着先做一遍行反转(这一行所有元素在初始和目标矩阵的都不同时),然后再做列交换,然而写了半天也不知道这个策略怎么写,从前往后走一遍的话不能保证最优。
说实话题解的做法我不太理解原理,但大致也觉得这么是对的。
题解中n+m+1设为最大交换次数,我感觉最大也就是m + n/2,不知道这样理解对不对。
具体步骤:
1.将初始矩阵所有列依次放到第一列(我的理解是这样,第一是因为这里的规则是进行行反转,列交换,如果是列反转,行交换的话,就是所有行依次放到第一行了, 第二是后面从前往后查看是否有列相同或者交换可得到,这在某种意义上进行了枚举,每一种可能都进行了尝试,以每一列为基准进行尝试,这与第二步也有关)
2. 对比当前第一列,也就是交换之前的1到n中某一列的元素是不是和目标矩阵一样,不一样就进行行反转
3.从前到后看每一列,如果当前列与目标矩阵中的当前列相同或者可以交换得到,那么就计算次数并与上次结果比较大小,如果不同且无法交换得到,那么这种尝试是失败的(这里注意最后比较的时候是从当前列而不是下一列,为了判断这一列是不是相同)
下面是代码
#include<bits/stdc++.h>
using namespace std;
#define maxn 110
int terms,n,m,inti[maxn][maxn],des[maxn][ma