金币阵列问题
问题描述:
有m´ n(m <= 100,n <= 100)个金币在桌面上排成一个m行n 列的金币阵列。每一枚金
币或正面朝上或背面朝上。用数字表示金币状态,0表示金币正面朝上,1 表示背面朝上。
金币阵列游戏的规则是:
(1)每次可将任一行金币翻过来放在原来的位置上;
(2)每次可任选2 列,交换这2 列金币的位置。
算法设计:
给定金币阵列的初始状态和目标状态,计算按金币游戏规则,将金币阵列从初始状态变
换到目标状态所需的最少变换次数。
数据输入:
文件中有多组数据。文件的第1行有1 个正整数k,表
示有k 组数据。每组数据的第1 行有2 个正整数m 和n。以下的m行是金币阵列的初始状
态,每行有n 个数字表示该行金币的状态,0 表示金币正面朝上,1 表示背面朝上。接着的
m行是金币阵列的目标状态。
«结果输出:
相应数据无解时
输出-1。
输入文件示例
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 1
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
输入文件示例
2
-1
算法思路:
1.穷举初始状态数组第一列交换到目标状态的数组的第k列,根据第一列的匹配
情况就可以知道对应的行是否应该进行变换。
2.然后在行变换确定之后,对余下的n-1列,根据更行的值就行匹配。

1 --------------------金币阵列_H---------------------------- 2 #ifndef 金币阵列_H 3 #define 金币阵列_H 4 5 #include<stdio.h> 6 #include<iostream> 7 #include<math.h> 8 9 void rowTransform(int** a,int rows,int columns,int row); 10 void columnTranform(int** a,int rows,int columns,int column1,int column2); 11 bool isColumnSame(int** a,int** b,int rows,int columns,int column1,int column2); 12 int timeNeed(int** a,int** b,int rows,int columns); 13 14 15 int timeNeed(int** a,int** b,int rows,int columns) 16 { 17 int count = INT_MAX;//变换的次数 18 int** temp;//暂存初始矩阵 19 temp = (int**)malloc(rows*sizeof(int*)); 20 for(int i=0;i<rows;i++) 21 temp[i] = (int*)malloc(columns*sizeof(int)); 22 for(int k=0;k<columns;k++) 23 { 24 for(int i=0;i<rows;i++) 25 for(int j=0;j<columns;j++) 26 temp[i][j] = a[i][j]; 27 int need = 0;//该种情况需要变换的次数 28 columnTranform(temp,rows,columns,0,k); 29 need++; 30 //查看第一列的每一行是否相等,如果不想等就进行行变换 31 for(int j=0;j<rows;j++) 32 { 33 if(temp[j][0]!=b[j][0]) 34 { 35 rowTransform(temp,rows,columns,j); 36 need++; 37 } 38 } 39 bool find; 40 //检查每列是否满足条件,如果满足则为一种变换的步骤,如果不能则交换 41 for(int i=0;i<columns;i++) 42 { 43 find = false; 44 if(isColumnSame(temp,b,rows,columns,i,i)) 45 { 46 find = true; 47 continue; 48 } 49 for(int j=i+1;j<columns;j++) 50 { 51 if(isColumnSame(temp,b,rows,columns,j,i)) 52 { 53 if(isColumnSame(temp,b,rows,columns,j,j)) 54 continue; 55 columnTranform(temp,rows,columns,i,j); 56 need++; 57 find = true; 58 break; 59 } 60 } 61 if(find = false) 62 break; 63 } 64 if(find&&count>need) 65 count = need; 66 } 67 for(int i=0;i<rows;i++) 68 free(temp[i]); 69 free(temp); 70 if(count==INT_MAX) 71 return -1; 72 return count; 73 } 74 //指定的行进行变换,取反 75 void rowTransform(int** a,int rows,int columns,int row) 76 { 77 for(int i=0;i<columns;i++) 78 a[row][i]^=1; 79 } 80 //两列交换 81 void columnTranform(int** a,int rows,int columns,int column1,int column2) 82 { 83 int temp; 84 if(column1==column2) 85 return; 86 for(int i=0;i<rows;i++) 87 { 88 temp = a[i][column1]; 89 a[i][column1] = a[i][column2]; 90 a[i][column2] = temp; 91 } 92 } 93 //判断两列是否相等 94 bool isColumnSame(int** a,int** b,int rows,int columns,int column1,int column2) 95 { 96 for(int i=0;i<rows;i++) 97 if(a[i][column1]!=b[i][column2]) 98 return false; 99 return true; 100 } 101 #endif 102 ——————————main.cpp——————————————— 103 int main() 104 { 105 FILE* input = fopen("input.txt","r"); 106 FILE* output = fopen("output.txt","w"); 107 if(input == NULL||output == NULL) 108 { 109 printf("无该文件或无法创建文件!\n"); 110 exit(1); 111 } 112 int **a,**b; 113 int rows = 0,columns = 0; 114 int count;//数据的组数 115 fscanf_s(input,"%d",&count); 116 117 for(int k=0;k<count;k++) 118 { 119 fscanf_s(input,"%d",&rows); 120 fscanf_s(input,"%d",&columns); 121 a = (int**)malloc(rows*sizeof(int*)); 122 b = (int**)malloc(rows*sizeof(int*)); 123 for(int i=0;i<rows;i++) 124 { 125 a[i] = (int*)malloc(columns*sizeof(int)); 126 b[i] = (int*)malloc(columns*sizeof(int)); 127 } 128 for(int i=0;i<rows;i++) 129 for(int j=0;j<columns;j++) 130 fscanf_s(input,"%d",&(a[i][j])); 131 for(int i=0;i<rows;i++) 132 for(int j=0;j<columns;j++) 133 fscanf_s(input,"%d",&(b[i][j])); 134 int times; 135 times = timeNeed(a,b,rows,columns); 136 fprintf_s(output,"%d\n",times); 137 fflush(output); 138 for(int i=0;i<rows;i++) 139 { 140 free(a[i]); 141 free(b[i]); 142 } 143 free(a); 144 free(b); 145 } 146 fclose(input); 147 fclose(output); 148 return 0; 149 }


浙公网安备 33010602011771号