问题描述: 有mxn(m<=100,n<=100)枚金币在桌面上排成一个m行n列的金币阵列。每一枚金币或正面朝上,或背面朝上。用数字表示金币状态,0表示正面朝上,1表示金币背面朝上。
金币游戏的规则是:(1)每次可将任一行金币翻过来放在原来的位置上(2)每次可任选2列,变换着2列金币的位置
算法设计:给定金币阵列的初始状态和目标状态,计算按金币游戏规则,将金币阵列从初始状态变换到目标状态所需的最少变换次数
分析:由于规则(2) 对(1) 有约束,故进行(2) 操作后不能进行(1)操作,基于此,可设计以下方案:
对原始阵列(A)1~n分别作为第1列进行行变换(A'),使之与目标列相匹配(同时统计变换次数),然后从第二列起目标列依次与A'相匹配, 同时进行列变换(统计变换次数),若不能找到即输出"-1",否则更新变换次数,最终输出可能的最小变换次数,最坏时间复杂度O(n^3*m)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define oo 0x3f3f3f3f//1061109567
void Swap_Column(char **temp,int m,int j1,int j2){
int i;
for(i = 0 ; i < m ; i ++)
if(temp[i][j1] != temp[i][j2]){
if(temp[i][j1] == '0'){
temp[i][j1] = '1';
temp[i][j2] = '0';
}
else{
temp[i][j1] = '0';
temp[i][j2] = '1';
}
}
}
void Row_Change(char **temp,int i,int n){
int j;
for(j = 0 ; j < n ; j ++){
temp[i][j] = (temp[i][j] == '0') ? '1':'0';
}
}
int Is_Same(char **goal_matrix,char **temp,int k,int r,int m){
int i;
for(i = 0 ; i < m ; i ++){
if(goal_matrix[i][k] != temp[i][r])
break;
}
if(i == m) return 1;
return 0;
}
void Copy(char **temp,char **init_matrix,int m){
int i;
for(i = 0 ; i < m ; i ++)
strcpy(temp[i],init_matrix[i]);
}
void Judge_And_Count(char **init_matrix,char **goal_matrix,int m,int n){
int i,j,k,r,count,flag,count1 = 0,least_num = oo;
char **temp = (char **)malloc(sizeof(char*)*m);
for(i = 0;i < m;i ++){
temp[i] = (char *)malloc(sizeof(char)*(n+1));
strcpy(temp[i],init_matrix[i]);
}
for(j = 0; j < n ; j ++){
count = 0;
flag = 1; //当前变换存在标志
if(j > 0) {
Swap_Column(temp,m,0,j);
count ++;
}
for(i = 0 ;i < m ; i ++)//行匹配
if(temp[i][0] != goal_matrix[i][0]){
Row_Change(temp,i,n);
count ++;
}
for(k = 1; k < n ; k ++){//列匹配
for(r = k ; r < n ; r ++){
if(Is_Same(goal_matrix,temp,k,r,m)){
if(k != r){//k!=r,否则会多统计一次变换
Swap_Column(temp,m,k,r);
count ++;
}
break;
}
}
if(r == n){
count1 ++; //count1:整个阵列是否存在变换
flag = 0;
break;
}
}
if(flag && least_num > count)
least_num = count;
Copy(temp,init_matrix,m); //复原temp
}
printf("%d\n",count1 == n ? -1 : least_num);
}
int main(){
int m,n,i;
char **init_matrix,**goal_matrix;
while(scanf("%d%d",&m,&n) != EOF){
getchar();
//二维数组的动态开辟
init_matrix = (char **)malloc(sizeof(char*)*m);
goal_matrix = (char **)malloc(sizeof(char*)*m);
for(i = 0;i < m;i ++){
init_matrix[i] = (char *)malloc(sizeof(char)*(n+1));
goal_matrix[i] = (char *)malloc(sizeof(char)*(n+1));
}
for(i = 0; i < m;i ++)
scanf("%s",init_matrix[i]);
for(i = 0; i < m;i ++)
scanf("%s",goal_matrix[i]);
Judge_And_Count(init_matrix,goal_matrix,m,n);
}
return 0;
}
测试样例:
4 3
101
000
110
101
101
111
011
101---->2
4 3
101
000
100
111
110
111
011
101--->-1
[参考]:http://blog.csdn.net/softwareldu/article/details/10509999