标签:col emc exp 通过 pre 技术 顺序 循环 std
给出01矩阵,请问是否能通过两个操作使得 原01矩阵变换到目标的01矩阵
操作1:行变换 —— 01翻转
操作2:列变换 —— 交换两列
模拟题
按顺序模拟即可,
第一步:必须找到某一列作为第一列,通过 0 次或多次的行变换变成与目标矩阵的第一列一样。
第二步:通过交换列,得到与目标矩阵一样的。
注意贪心交换无法达到最小步数
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int N = 2e2+10; 5 const int inf = 0x3f3f3f3f; 6 7 // 原数组 source 目标数组 Aim 操作数组 8 int Src[N][N] , Aim[N][N] , tmp[N][N] ; 9 int n , m , cnt , Ans ; 10 11 //判断操作数组的某一列 是否和 目标数组当前列 相符 12 bool SameCol( int C1 , int C2 ){ 13 14 for( int i = 1 ; i <= n ; i ++ ){ 15 if( tmp[i][C1] != Aim[i][C2] ) 16 return false ; 17 } 18 return true; 19 } 20 21 //操作1: 对操作数组 某一行金币进行翻转 22 void Filp( int Row ){ 23 for( int j = 1 ; j <= m ; j++ ){ 24 tmp[Row][j] ^= 1 ; 25 } 26 cnt ++ ; 27 } 28 29 //操作2: 对操作数组 某两列进行交换 30 void SwapCol( int C1 , int C2 ){ 31 32 if( C1 == C2 ) return ; //如果 两列相同则不作处理 33 34 for( int i = 1 ; i <= n ; i++ ){ 35 swap( tmp[i][C1] , tmp[i][C2] ); 36 } 37 cnt ++ ; 38 } 39 40 void Input(){ 41 42 scanf("%d%d",&n,&m); 43 44 for( int i = 1 ; i <= n ; i++ ){ 45 for( int j = 1 ; j <= m ; j++ ){ 46 scanf("%d",&Src[i][j] ); 47 } 48 } 49 50 for( int i = 1 ; i <= n ; i++ ){ 51 for( int j = 1 ; j <= m ; j++ ){ 52 scanf("%d",&Aim[i][j] ); 53 } 54 } 55 56 } 57 58 void Solve(){ 59 60 Ans = inf ; 61 62 //选取某一列作为第一列 63 for( int Col = 1 ; Col <= m ; Col ++ ){ 64 65 //操作前应把过程更新的 cnt,tmp[][] 初始化 66 cnt = 0 ; 67 memcpy( tmp , Src , sizeof Src ) ; 68 69 //把对应行交换作为第一列 70 SwapCol( Col , 1 ); 71 72 //如果当前位置不符合,则使用“操作1-翻转硬币”使得符合. 73 for( int i = 1 ; i <= n ; i ++ ){ 74 if( tmp[i][1] != Aim[i][1] ) 75 Filp(i) ; 76 } 77 78 //以后不能再用“操作1-翻转硬币”,因为固定了第一列, 79 //如果使用一次“操作1-翻转硬币”,就会破坏当前第一列 80 81 //***剩下来的任务***:通过交换两列,使得剩下来的都符合Aim 82 83 bool Successful_Col ; 84 //外循环枚举Aim数组的列位置 85 for( int k = 2 ; k <= m ; k ++ ){ 86 87 Successful_Col = false ; 88 89 //判断当前列是否已经匹配上 90 if( SameCol( k , k ) ){ 91 Successful_Col = true ; 92 continue ; 93 } 94 95 //内循环枚举tmp数组列的位置,前k列已经匹配,应从[k+1,m]选择 96 97 for( int j = k+1 ; j <= m ; j ++ ){ 98 if( SameCol( j , k ) && !SameCol( j , j ) ){ 99 Successful_Col = true ; 100 SwapCol( j , k ) ; 101 break; 102 } 103 } 104 105 if( !Successful_Col ) break; 106 } 107 108 if( Successful_Col && Ans > cnt ){ 109 //printf("Col : %d , %d\n",Col,cnt); 110 Ans = cnt ; 111 } 112 } 113 if( Ans != inf ) 114 printf("%d\n",Ans); 115 else{ 116 printf("-1\n"); 117 } 118 } 119 int main(){ 120 121 Input(); 122 Solve(); 123 124 return 0; 125 } 126 /* 127 3 6 128 129 0 0 0 0 0 1 130 0 0 1 1 1 1 131 0 1 0 0 0 0 132 133 0 0 0 0 0 1 134 0 1 1 1 0 0 135 0 0 0 0 1 0 136 137 */
标签:col emc exp 通过 pre 技术 顺序 循环 std
原文地址:https://www.cnblogs.com/Osea/p/11515051.html