问题描述:ios
有m x n (m<=100, n<=100 ) 个金币在桌面上排成一个m行n 列的金币阵列。每一枚金币或正面朝上或背面朝上。用数字表示金币状态,0表示金币正面朝上,1 表示背面朝上。金币阵列游戏的规则是:
(1)每次可将任一行金币翻过来放在原来的位置上;
(2)每次可任选2 列,交换这2 列金币的位置。
算法设计:
算法
给定金币阵列的初始状态和目标状态,计算按金币游戏规则,将金币阵列从初始状态变换到目标状态所需的最少变换次数。ide
数据输入:
由文件input.txt给出输入数据。文件中有多组数据。文件的第1行有1 个正整数k,表示有k 组数据。每组数据的第1 行有2 个正整数m 和n。如下的m行是金币阵列的初始状态,每行有n 个数字表示该行金币的状态,0 表示金币正面朝上,1 表示背面朝上。接着的m行是金币阵列的目标状态。
结果输出:spa
将计算出的最少变换次数按照输入数据的次序输出到文件output.txt。相应数据无解时输出-1。
输入文件示例 输出文件示例
input.txt
2
4 3
1 0 1
0 0 0
1 1 0
1 0 1
1 0 1
1 1 1
0 1 1
设计
1 0 1orm
4 3
1 0 1
0 0 0
1 0 0
1 1 1
1 1 0
1 1 1
0 1 1
1 0 1游戏
output.txt
2
ci
-1input
2015年9月21日:it
#include<malloc.h> #include<iostream> #include<fstream> #define INF 1<<30 using namespace std; /*将矩阵a的第col行进行行变换*/ void transfer_row(int array[],int n) { int i=0; for(i=0;i<n;i++) array[i]^=1; } /*交换矩阵a的i和j列*/ void swap_columns(int **a,int m,int n,int i,int j) { int k=0; while(k<m) { int tmp=a[k][i]; a[k][i]=a[k][j]; a[k][j]=tmp; k++; } } /*比较矩阵a的第col_a列和矩阵b的第col_b列是否相等*/ int compare_column(int **a,int **b,int m,int n,int col_a,int col_b) { int k=0; for(k=0;k<m;k++) { if(a[k][col_a]!=b[k][col_b]) return 0; } return 1; } /*将矩阵src的内容复制到矩阵dest中*/ void copy_array(int** dest,int **src,int m,int n ) { for(int i=0;i<m;i++) for(int j=0;j<n;j++) dest[i][j]=src[i][j]; } /**寻找将原始矩阵a变换到目标矩阵b的最少变换次数,若是不能将a变换到b,那么返回-1*/ int find(int **a,int **b,int m,int n) { /**flag记录一次变换,是否可以达到目标矩阵*/ int flag=0; /**best为最少交换次数,初始值为无穷大*/ int best=INF; /**count记录一次变换过程当中须要进行交换的次数*/ int count=0; int **tmp=(int **)malloc(sizeof(int *)*m); int i=0; for(i=0;i<m;i++) tmp[i]=(int *)malloc(sizeof(int)*n); copy_array(tmp,a,m,n); /*以列变换为基准,一次将初始矩阵a的每一列与第一列交换*/ for(i=0;i<n;i++) { swap_columns(a,m,n,i,0); if(i!=0) count++; //int j=0; /*列变换后,将a的新的第一列和目标矩阵b的第一列比较, 若a中第一列中某行元素与b中第一列相应行的元素不相等,则将a中该行进行变换 完成此过程后,a的第一列元素和b的第一列元素彻底相同,下面列变换过程当中就不能再进行行变换! */ for(int j=0;j<m;j++) { if(a[j][0]!=b[j][0]) { transfer_row(a[j],n); count++; } } //int k=0; /**从a中一次寻找相应的某些列使得这些列一次和b中的第2到第n列相等, 若是查找成功,则说明此种变换能够达到目标状态,而后将此种变换所花费的变换次数和当前最有变换次数best比较 若是小于best,则将best更新此种变换的花费的变换次数 */ for(int j=1;j<n;j++) { flag=0; for(int k=j;k<n;k++) { if(compare_column(a,b,m,n,k,j)) // 比较a的第k列和b的第j列是否相等 { if(k!=j) { count++; swap_columns(a,m,n,k,j); // 若是a与目标状态b的相同列的位置不同就对a进行列变换 } flag=1; // 每次若是a中有与b这一列相同的列就直接置flag为1而后跳出循环 break; } } if(flag==0) break; //count=0; } if(flag==1&&best>count) best=count; count=0; copy_array(a,tmp,m,n); } if(best<INF) return best; else return -1; } int main() { ifstream in("input.txt"); int m,n; cin>>m>>n; int **a=(int **)malloc(sizeof(int*)*m); int **b=(int **)malloc(sizeof(int*)*m); for(int i=0;i<m;i++) { a[i]=(int *)malloc(sizeof(int)*n); b[i]=(int *)malloc(sizeof(int)*n); } for(int i=0;i<m;i++) for(int j=0;j<n;j++) cin>>a[i][j]; for(int i=0;i<m;i++) for(int j=0;j<n;j++) cin>>b[i][j]; int res=find(a,b,m,n); cout<<res<<endl; }