偶数矩阵-回溯
给你一个n*n的01矩阵(每个元素非0即1),你的任务是把尽量少的0变成1,使得每个元素的上、下、左、右的元素(如果存在的话)之和均为偶数。如图所示的矩阵至少要把3个0变成1,最终如图所示,才能保证其为偶数矩阵。
【输入格式】 输入的第一行为数据组数T(T<30)。每组数据的第一行为正整数n(1 < n < 15);接下来的n行每行包含n个非0即1的整数,相邻整数间用一个空格隔开。
【输出格式】 对于每组数据,输出被改变的元素的最小个数。如果无解,应输出-1。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <mem.h> 3 /*输入测试 4 1 5 3 6 0 0 0 7 1 0 0 8 0 0 0 9 1 10 6 11 0 0 0 0 0 0 12 1 0 0 0 0 0 13 0 0 0 0 0 0 14 0 0 0 0 0 0 15 0 0 0 0 0 0 16 0 0 0 0 0 0 17 1 18 14 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 0 1 0 0 0 0 0 0 0 0 0 0 0 0 21 0 0 0 0 0 0 0 0 0 0 0 0 0 0 22 0 1 0 0 0 0 0 0 0 0 0 0 0 0 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 24 0 1 0 0 0 0 0 0 0 0 0 0 0 0 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 26 0 1 0 0 0 0 0 0 0 0 0 0 0 0 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 28 0 1 0 0 0 0 0 0 0 0 0 0 0 0 29 0 0 0 0 0 0 0 0 0 0 0 0 0 0 30 0 1 0 0 0 0 0 0 0 0 0 0 0 0 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 32 0 1 0 0 0 0 0 0 0 0 0 0 0 0 33 */ 34 35 int T,n; 36 int map[256];//矩阵数组 37 int minuteTimes=9999;//初始化最大转换数9999,也就是无法形成偶数矩阵 38 int currentTimes=0;//当前转换数 39 int dirction[]={16,1,-1,-16};//偶数矩阵特性 40 //int recode[225]={0};//记录形成的偶数矩阵 41 42 43 //是否符合偶数矩阵特性 44 int isEven(int position) 45 { 46 int temp; 47 int index=0; 48 49 while(map[position+dirction[index++]]==2); 50 51 temp=map[position+dirction[--index]]; 52 53 for(int i=index+1;i<4;i++) 54 { 55 if(map[position+dirction[i]]<2) temp^=map[position+dirction[i]]; 56 } 57 58 return temp; 59 } 60 61 //寻找最小翻转次数 62 void findMinuteTimes(int depth) 63 { 64 if(depth>(n<<4)+n) 65 { 66 67 if(currentTimes<minuteTimes) 68 { 69 //记录数组-调试使用 70 /*memset(recode,0,sizeof(recode)); 71 for(int i=0;i<256;i++) 72 { 73 if(map[i]==1) recode[(i/16-1)*15+i%16-1]=1; 74 }*/ 75 minuteTimes=currentTimes; 76 } 77 78 return; 79 } 80 if(map[depth]<2 && isEven(depth)) 81 { 82 for(int i=0;i<4;i++) 83 { 84 if(map[depth+dirction[i]]>0) continue; 85 86 map[depth+dirction[i]]=1; 87 currentTimes++; 88 89 int temp; 90 switch(i) 91 { 92 //当选择步长为16时,应从+1,-15,-17,-32中不超出数组的地方开始搜索 93 case 0: 94 if( map[depth+dirction[i]]+1!=2) 95 { 96 temp=1; 97 break; 98 } 99 //当选择步长为1时,应从-15,-17,-32中不超出数组的地方开始搜索 100 case 1: 101 if( map[depth+dirction[i]]-15!=2) 102 { 103 temp=-15; 104 break; 105 } 106 //当选择步长为-1时,应从-17,-32中不超出数组的地方开始搜索 107 case 2: 108 if( map[depth+dirction[i]]-17!=2) 109 { 110 temp=-17; 111 break; 112 } 113 //当选择步长为-16时,应从-32中不超出数组的地方开始搜索 114 case 3: 115 if( map[depth+dirction[i]]-32!=2) 116 { 117 temp=-32; 118 break; 119 } 120 //否则递增1再开始搜索 121 default: 122 temp=1; 123 break; 124 } 125 findMinuteTimes(depth+temp); 126 map[depth+dirction[i]]=0; 127 currentTimes--; 128 } 129 } 130 else 131 findMinuteTimes(depth+1); 132 133 } 134 135 int main() 136 { 137 scanf("%d",&T); 138 while(T--) 139 { 140 scanf("%d",&n); 141 minuteTimes=9999; 142 for(int i=0;i<16;i++) 143 { 144 for(int j=0;j<16;j++) 145 { 146 if(i==0 || j==0) map[(i<<4)+j]=2; 147 else if(i<=n && j<=n) scanf("%d",map+(i<<4)+j); 148 else map[(i<<4)+j]=2; 149 } 150 } 151 findMinuteTimes(0); 152 printf("%d\n",minuteTimes==9999?-1:minuteTimes); 153 } 154 //调试输出 155 /*for(int i=0;i<n;i++) 156 { 157 for(int j=0;j<n;j++) 158 { 159 printf("%d ",recode[(i*15)+j]); 160 } 161 printf("\n"); 162 } 163 for(int i=0;i<16;i++) 164 { 165 for(int j=0;j<16;j++) 166 { 167 printf("%d ",map[(i<<4)+j]); 168 } 169 printf("\n"); 170 }*/ 171 172 return 0; 173 }