問題描述: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; }