金币阵列问题

来源:互联网 发布:linux卸载subversion 编辑:程序博客网 时间:2024/04/28 08:02

问题描述: 有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//1061109567void 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

1 0
原创粉丝点击