金幣陣列問題

問題描述:ios

有m x n (m<=100, n<=100 ) 個金幣在桌面上排成一個m行n 列的金幣陣列。每一枚金幣或正面朝上或背面朝上。用數字表示金幣狀態,0表示金幣正面朝上,1 表示背面朝上。金幣陣列遊戲的規則是:
(1)每次可將任一行金幣翻過來放在原來的位置上;
(2)每次可任選2 列,交換這2 列金幣的位置。

算法設計:
算法

        給定金幣陣列的初始狀態和目標狀態,計算按金幣遊戲規則,將金幣陣列從初始狀態變換到目標狀態所需的最少變換次數。ide


數據輸入:
        由文件input.txt給出輸入數據。文件中有多組數據。文件的第1行有1 個正整數k,表示有k 組數據。每組數據的第1 行有2 個正整數m 和n。如下的m行是金幣陣列的初始狀態,每行有n 個數字表示該行金幣的狀態,0 表示金幣正面朝上,1 表示背面朝上。接着的m行是金幣陣列的目標狀態。

結果輸出:
spa

        將計算出的最少變換次數按照輸入數據的次序輸出到文件output.txt。相應數據無解時輸出-1。
輸入文件示例 輸出文件示例
input.txt 
2
4 3
1 0 1
0 0 0
1 1 0
1 0 1

1 0 1
1 1 1
0 1 1
設計

1 0 1orm


4 3
1 0 1
0 0 0
1 0 0
1 1 1

1 1 0
1 1 1
0 1 1
1 0 1
遊戲


output.txt
2
ci

-1input


2015年9月21日:it

#include<malloc.h>
#include<iostream>
#include<fstream>


#define INF 1<<30


using namespace std;
/*將矩陣a的第col行進行行變換*/
void transfer_row(int array[],int n)
{
    int i=0;
    for(i=0;i<n;i++)
        array[i]^=1;
}

/*交換矩陣a的i和j列*/
void swap_columns(int **a,int m,int n,int i,int j)
{
    int k=0;
    while(k<m)
    {
        int tmp=a[k][i];
        a[k][i]=a[k][j];
        a[k][j]=tmp;
        k++;
    }
}

/*比較矩陣a的第col_a列和矩陣b的第col_b列是否相等*/
int compare_column(int **a,int **b,int m,int n,int col_a,int col_b)
{
    int k=0;
    for(k=0;k<m;k++)
    {
        if(a[k][col_a]!=b[k][col_b])
        return 0;
    }
    return 1;
}

/*將矩陣src的內容複製到矩陣dest中*/
void copy_array(int** dest,int **src,int m,int n )
{
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            dest[i][j]=src[i][j];
}


/**尋找將原始矩陣a變換到目標矩陣b的最少變換次數,若是不能將a變換到b,那麼返回-1*/
int find(int **a,int **b,int m,int n)
{
    /**flag記錄一次變換,是否可以達到目標矩陣*/
    int flag=0;

    /**best爲最少交換次數,初始值爲無窮大*/
    int best=INF;

    /**count記錄一次變換過程當中須要進行交換的次數*/
    int count=0;

    int **tmp=(int **)malloc(sizeof(int *)*m);
    int i=0;
    for(i=0;i<m;i++)
        tmp[i]=(int *)malloc(sizeof(int)*n);
    
    copy_array(tmp,a,m,n);


    /*以列變換爲基準,一次將初始矩陣a的每一列與第一列交換*/
    for(i=0;i<n;i++)
    {
        swap_columns(a,m,n,i,0);
        if(i!=0)
            count++;
        //int j=0;
        /*列變換後,將a的新的第一列和目標矩陣b的第一列比較,
        若a中第一列中某行元素與b中第一列相應行的元素不相等,則將a中該行進行變換
        完成此過程後,a的第一列元素和b的第一列元素徹底相同,下面列變換過程當中就不能再進行行變換!
        */
        for(int j=0;j<m;j++)
        {
            if(a[j][0]!=b[j][0])
            {
                transfer_row(a[j],n);
                count++;
            } 
        }

        //int k=0;
        /**從a中一次尋找相應的某些列使得這些列一次和b中的第2到第n列相等,
        若是查找成功,則說明此種變換能夠達到目標狀態,而後將此種變換所花費的變換次數和當前最有變換次數best比較
        若是小於best,則將best更新此種變換的花費的變換次數
        */
        for(int j=1;j<n;j++)
        {
            flag=0;
            for(int k=j;k<n;k++)
            {
                if(compare_column(a,b,m,n,k,j))  // 比較a的第k列和b的第j列是否相等
                {
                    if(k!=j)
                    { 
                        count++;
                        swap_columns(a,m,n,k,j); // 若是a與目標狀態b的相同列的位置不同就對a進行列變換
                    } 
                    flag=1;         // 每次若是a中有與b這一列相同的列就直接置flag爲1而後跳出循環
                    break;
                }
            }
            if(flag==0)
                break;
            //count=0;
        }
        if(flag==1&&best>count)
            best=count;
        count=0;
        copy_array(a,tmp,m,n);
    }
    if(best<INF)
        return best;
    else
        return -1;
}


int main()
{
    ifstream in("input.txt");
    int m,n;
    cin>>m>>n;
    int **a=(int **)malloc(sizeof(int*)*m);
    int **b=(int **)malloc(sizeof(int*)*m);
    for(int i=0;i<m;i++)
    {
        a[i]=(int *)malloc(sizeof(int)*n);
        b[i]=(int *)malloc(sizeof(int)*n);
    }

    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            cin>>a[i][j];
    for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
            cin>>b[i][j];

    int res=find(a,b,m,n);
    cout<<res<<endl;
}
相關文章
相關標籤/搜索