偶数矩阵-回溯

 给你一个n*n的01矩阵(每个元素非0即1),你的任务是把尽量少的0变成1,使得每个元素的上、下、左、右的元素(如果存在的话)之和均为偶数。如图所示的矩阵至少要把3个0变成1,最终如图所示,才能保证其为偶数矩阵。
 

【输入格式】      输入的第一行为数据组数T(T<30)。每组数据的第一行为正整数n(1 < n < 15);接下来的n行每行包含n个非0即1的整数,相邻整数间用一个空格隔开。
【输出格式】      对于每组数据,输出被改变的元素的最小个数。如果无解,应输出-1。

 

  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 }
View Code

 

posted @ 2014-03-10 22:10  随心随想  阅读(647)  评论(0编辑  收藏  举报