POJ 2965 The Pilots Brothers' refrigerator(反转)

Description
4*4矩阵,矩阵上每个元素都有两种状态开和关,给定初始状态,和状态转移,求从初始状态到目标状态(所有元素都是开状态)的最小步骤数以及步骤(每操作一个开关,此开关所在行列所有开关均被操作)
Input
一个4*4矩阵表示开关状态,+表示关,-表示开
Output
输出从初始状态到目标状态的最小步骤数以及步骤
Sample Input
- + - -
- - - -
- - - -
- + - -
Sample Output
6
1 1
1 3
1 4
4 1
4 3
4 4
Solution
要使一个为+变为-,必须其相应的行和列的操作数为奇数;可以证明,如果+位置对应的行和列上每一个位置都进行一次操作,则整个图只有这一+位置的符号改变,其余都不会改变.
设置一个4*4的整型数组,初值为零,用于记录每个点的操作数,那么在每个+上的行和列的的位置都加1,得到结果模2(因为一个点进行偶数次操作的效果和没进行操作一样),然后计算整型数组中1的个数即为操作数,1的位置为要操作的位置(其他原来操作数为偶数的因为操作并不发生效果,因此不进行操作)
按以上步骤使数组中值都为‘-’
Code

#include<stdio.h>
int main()
{
    int i,j,k,open[4][4],ii[16],jj[16],min=0;
    char oo[4][5];
    for(i=0;i<4;i++)
        for(j=0;j<5;j++)
            scanf("%c",&oo[i][j]);
    for(i=0;i<4;i++)//初始化 
        for(j=0;j<4;j++)
            open[i][j]=0;
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            if(oo[i][j]=='+')//遇到+则对其所在行列所有开关进行操作 
            {
                open[i][j]=!open[i][j];
                for(k=0;k<4;k++)
                {
                    open[k][j]=!open[k][j];
                    open[i][k]=!open[i][k];
                }
            }
        }
    for(i=0;i<4;i++)
        for(j=0;j<4;j++)
        {
            if(open[i][j]==1)//记录步骤 
            {
                ii[min]=i+1;
                jj[min]=j+1;
                min++;//步骤数加一 
            }
        }   
    printf("%d\n",min);
    for(i=0;i<min;i++)
        printf("%d %d\n",ii[i],jj[i]);  
}

你可能感兴趣的:(POJ 2965 The Pilots Brothers' refrigerator(反转))