金幣陣列問題

iamzxf發表於2013-08-29

    問題描述:有m*n枚金幣在桌面上排列成一個m行n列的金幣陣列。每一枚金幣或正面朝上,或背面朝上。用數字表示金幣狀態,0表示正面朝上,1表示背面朝上。

金幣陣列遊戲的規則是:

    (1)每次將任一行金幣翻過來放在原來的位置上。

    (2)每次可以任選2列,交換這2列金幣的位置。

    任務:給定金幣的初始狀態和目標狀態,程式設計計算按金幣遊戲規則,將金幣排列從初始狀態變換到目標狀態所需的最少變換次數。

    解題思路:

    本例的實質是將一個二進位制矩陣從一種形式利用相應規則變換到另一種形式。提供的規則有兩種:

    (1)將某一行的金幣翻轉;

    (2)將某兩列進行交換。

    在這兩種操作中,第一種操作可能會影響到某一行或者某一列中已經排列好的相關元素,因此,首先利用該規則進行變換,而後續的操作則不再利用該規則。演算法的具體思路如下:

    (1)將矩陣中的每一列作為第1列,並利用第一個規則將第1列中的相關元素與目標矩陣中第1列的元素進行配對,如果不相同,則利用每1個規則進行翻轉;

    (2)從第2列開始,將處理後的列與目標列進行比較,如果相同,則轉下一列;如果不相同,看是否可以通過列的交換完成,如果不可以,則無法做到,如果可以,則繼續掃描,直至所有的列描述完成為止。

參考程式:

#include <stdio.h>
 
inta[4][3]={{1,0,1},{0,0,0},{1,1,0},{1,0,1}}; //source
intb[4][3]={{1,0,1},{1,1,1},{0,1,1},{1,0,1}}; //target
int temparr[4][3];
int m=4, n=3;
int count;
 
 
void main()
{
    voidtrans1(int);       //對某一行進行翻轉
    voidtrans2(int, int);  //對某兩列進行互換
    boolsame(int, int);    //判斷temparr中的列和b中的列是否相同
   
    inti,j,k;
   
    intanswer=9999;
 
//整體思路,將每一列運用列交換作為第1列,然後對每一行進行判斷,如果元素//與目標元素不相等,
 
//進行翻轉處理,再向後判斷相關列是否相同。
    for(k=0;k<m;k++)
    {
        //copyarray
        for(i=0;i<m;i++)   
            for(j=1;j<n;j++)
                temparr[i][j]=a[i][j];
       
        count=0;
        trans2(1,k);//將第k列與第1列互換
 
       
        //對所有行的第1個元素與目標陣列對應的元素進行比較,如果不同
        //進行按行變換
        for(i=0;i<m;i++)
        {
            if(temparr[i][0]!=b[i][0])
                trans1(i); 
        }
       
 
        //檢查每一列是否滿足條件
        boolfound;
        for(i=0;i<n;i++)
        {
            found=false;
            if(same(i,i))
            {
                found=true;continue;
            }
 
            for(j=i+1;j<n;j++)//判斷是否可以通過後續列的交換達到目的
            {
                if(same(i,j))
                {
                    trans2(i,j);
                    found=true;
                    break;
                }
            }
 
            if(found==false)
                break;
        }
 
        if(found==true) answer=count;
    }
    if(answer<9999)
        printf("yes.the steps needed is %d.\n",count);
    else
        printf("no.\n");
 
}
 
void trans1(int j)
//對某一行進行翻轉
{
    for(inti=0;i<3;i++)
        temparr[j][i]=1-temparr[j][i];// a[j][i]^=1; //異或運算也可以
 
    count++;
}
 
 
void trans2(int i,int j)
//對兩列進行互換
{
    for(intk=0;k<4;k++)
    {
        inttemp=temparr[k][i];
        temparr[k][i]=temparr[k][j];
        temparr[k][j]=temp;
    }
 
    if(i!=j) count++;
}
 
 
bool same(int j,int i)
//判斷兩列是否相同
{
    intk;
    boolflag=true;
 
    for(k=0;k<m;k++)
    {
        if(temparr[k][i]!=b[k][j])
        {
            flag=false;
            break;
        }
    }
    returnflag;
}


相關文章