金幣陣列問題



題目描述:

金幣陣列問題。
有m*n枚金幣在桌面上排成一個(gè)金幣陣列。每一個(gè)金幣正面朝上,或背面朝上蕉汪,分別用0和1表示。 金幣陣列游戲的規(guī)則是:(1)每次可將任一行金幣翻過來放在原來的位置上逞怨;(2)每次可任選2列者疤,交換這2列金幣的位置。
給定金幣的初始狀態(tài)和目標(biāo)狀態(tài)叠赦,計(jì)算按金幣游戲規(guī)則驹马,將金幣陣列從初始狀態(tài)變換到目標(biāo)狀態(tài)所需的最少變換次數(shù)。
示例:


一種正確思路

預(yù)先設(shè)定兩個(gè)數(shù)組眯搭,coin1和coin2,當(dāng)然也可以自行輸入
再設(shè)定一個(gè)替身數(shù)組窥翩,temparr

保證coin2數(shù)組在整個(gè)過程中不能被改變,coin1原數(shù)組也不能改變鳞仙,但是可以把coin1賦值給temparr,來改變temparr的值

以coin2的0號(hào)列為標(biāo)桿寇蚊,讓temparr的0號(hào)列與它比較,如果coin2[i][0]!=temparr[i][0]棍好,就把i這一行都翻轉(zhuǎn)仗岸,知道0號(hào)列的最后一個(gè)數(shù)字。

到這里借笙,coin2和temparr的0號(hào)列就相同了扒怖,同時(shí)也被固定下來,后面不能再改變业稼。所以盗痒,后續(xù)的列就不能在整行地翻轉(zhuǎn),因?yàn)檫@樣會(huì)改變0號(hào)列。后續(xù)的列只能通過交換位置的方式變成目標(biāo)陣列俯邓。

如果后續(xù)的列交換位置后骡楼,元素都能和目標(biāo)陣列匹配,則證明最初拿temparr0號(hào)列與coin2的0號(hào)列比較的決定是正確地稽鞭,此時(shí)輸出交換的次數(shù)即可鸟整。

如果后續(xù)的列和目標(biāo)陣列不匹配,則證明最初拿temparr0號(hào)列與coin2的0號(hào)列比較的決定是錯(cuò)誤的朦蕴。應(yīng)該讓coin1給temparr重新賦值篮条,再讓temparr的1號(hào)列進(jìn)行此過程,看能否行得通吩抓。如果再不行涉茧,就temparr的2號(hào)列......如此循環(huán),直到temparr的最后一列疹娶。

假如temparr的列都不行降瞳,則證明coin1根本不可能轉(zhuǎn)換到coin2,輸出“無法轉(zhuǎn)換”蚓胸,結(jié)束程序。

代碼:
#include<stdio.h>
#define row 4
#define col 3

int coin1[row][col]={{1,0,1},{0,1,0},{1,1,0},{1,0,1}}; //source  
int coin2[row][col]={{0,0,1},{1,1,0},{1,0,0},{1,1,0}}; //target 除师,不可被修改
int temparr[row][col];
int number=0;                //轉(zhuǎn)換的次數(shù)
int minnum=9999;

void trans1(int i)           //第i行翻轉(zhuǎn)
{
    int j;
    for(j=0;j<col;j++)
    {
        temparr[i][j]=1-temparr[i][j];
    }
    number++;

}

void trans2(int i,int j)    //第i列與第j列互換
{
    int temp,k;
    for(k=0;k<row;k++)
    {
        temp=temparr[k][i];
        temparr[k][i]=temparr[k][j];
        temparr[k][j]=temp;

    }
    if(i!=j)
        number++;
}

int judge(int i,int j)    //temparr的i列是否和coin2的j列相同
{
    int flag;
    for(int k=0;k<row;k++)
    {
        flag=1;
        if(temparr[k][i]!=coin2[k][j])
        {
            flag=0;
            break;
        }
    }
    
    return flag;
}


int main()
{
    int i,j,k;
    for(i=0;i<col;i++)    //代表coin1的列
    {
        //給替身數(shù)組賦值
        for(j=0;j<row;j++)
        {
            for(k=0;k<col;k++)
            {
                temparr[j][k]=coin1[j][k];
            }
        }
        
        number=0;           
        trans2(0,i);                 //temparr數(shù)組的列先做交換沛膳,把其他列放到第一列的位置
    

        for(j=0;j<row;j++)        //判斷temparr的0號(hào)列和coin2的0號(hào)列是否相同,不同則翻轉(zhuǎn)
        {
            if(temparr[j][0]!=coin2[j][0])
            {
                trans1(j);         //如果第1列不匹配汛聚,那么行全部翻轉(zhuǎn)
            }
        }

        int found;
        for(j=0;j<col;j++)         //代表coin2锹安,從第2行開始,到最后一行
        {
            found=0;
            for(k=j;k<col;k++)     //代表temparr倚舀,從第2行開始叹哭,直到最后一行
            {
                if(judge(k,j))
                {
                    found=1;
                    trans2(k,j);
                    break;
                }
            }
            if(!found)
            {
                break;
            }
        }
        if(found)
        {
            minnum=number;
        }
    
    }
    if(minnum<9999)
    {
        printf("次數(shù)為:%d\n",minnum);
        return 0;
    }else{
        printf("No!\n");
        return 0;
    }
    return 0;
}

當(dāng)前數(shù)組下痕貌,轉(zhuǎn)換次數(shù)為5次



覺得正確但是錯(cuò)誤的一種思路:

從0號(hào)行開始判斷风罩,如果coin1和coin2的某一行的1的個(gè)數(shù)相加等于col的大小,則翻轉(zhuǎn)
如果coin1某一行的1的個(gè)數(shù)舵稠,等于coin2的某一行的1的個(gè)數(shù)超升,則不需要翻轉(zhuǎn)
如果coin1和coin2的某一行的1的個(gè)數(shù)既不相等,相加也不等于col的大小哺徊,則無法翻轉(zhuǎn)

此種分析看似合理室琢,代碼也能寫出來,但是col為偶數(shù)時(shí)落追,此程序會(huì)混亂盈滴,col為奇數(shù),則能正常執(zhí)行

下面是此種情況的代碼:

#include<stdio.h>
#define row 4
#define col 3

int main(){
    int number=0;//記錄轉(zhuǎn)換的次數(shù)
    int i,j,k;

    /*
    int coin1[row][col];
    int coin2[row][col];
    printf("輸入初始金幣陣列(%d行%d列):\n",row,col);
    for(i=0;i<row;i++){
        for(j=0;j<col;j++){
            scanf("%d",&coin1[i][j]);
        }
    }
    printf("目標(biāo)初始金幣陣列(%d行%d列):\n",row,col);
    for(i=0;i<row;i++){
        for(j=0;j<col;j++){
            scanf("%d",&coin2[i][j]);
        }
    }
    */

    int coin1[4][3]={{1,0,1},{0,1,0},{1,1,0},{1,0,1}}; //source  
    int coin2[4][3]={{0,0,1},{1,1,0},{1,0,0},{1,1,0}}; //target 轿钠,不可被修改
    

    int sum1=0,sum2=0,flag=1;

    //先對(duì)行操作
    for(i=0;i<row&&flag;i++){
        sum1=sum2=0;
        for(j=0;j<col;j++){             //求某一行1的個(gè)數(shù)
            sum1+=coin1[i][j];
            sum2+=coin2[i][j];
        }

        if(sum1+sum2==col){                 //需要某一行翻轉(zhuǎn)的情況
            flag=1;
            number++;
            for(k=0;k<col;k++){
                coin1[i][k]=(1-coin1[i][k]);
            }
        }else if(sum1==sum2){               //不需要翻轉(zhuǎn)
            flag=1;
        }
        else{                               //不能翻轉(zhuǎn)的情況
            flag=0;
        }
    }
    


    int flag1;
    if(flag==1){                            //flag為1巢钓,證明能轉(zhuǎn)換

        for(i=0;i<col;i++){                //控制coin2的列
            for(j=i;j<col;j++){            //控制coin1的列
                for(k=0;k<row;k++){        //控制coin1和coin2的行
                    flag1=1;
                    if(coin2[k][i]!=coin1[k][j]){
                        flag1=0;           //flag1==0,證明沒有成功匹配
                        break;
                    }
                }

                if(!flag1){
                    continue;
                }
                if(flag1){//找到匹配病苗,進(jìn)行列交換
                    for(k=0;k<row;k++){      
                        int temp;
                        temp=coin1[k][j];
                        coin1[k][j]=coin1[k][i];
                        coin1[k][i]=temp;
                    }
                    number++;
                }
                int flag2=1;
                for(int a=0;a<row;a++){
                    for(int b=0;b<col;b++){
                        if(coin1[a][b]!=coin2[a][b])
                        {
                            flag2=0;
                        }
                    }
                }
                if(flag2){
                    printf("轉(zhuǎn)換%d次\n",number);
                    return 0;
                }
                break;
            }
        }

    }else{                                  //flag不為1,證明不能轉(zhuǎn)換
        printf("不能轉(zhuǎn)換竿报!\n");
        return 0;
    }
    return 0;
}



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末铅乡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子烈菌,更是在濱河造成了極大的恐慌阵幸,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件芽世,死亡現(xiàn)場(chǎng)離奇詭異挚赊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)济瓢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門荠割,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人旺矾,你說我怎么就攤上這事蔑鹦。” “怎么了箕宙?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵嚎朽,是天一觀的道長。 經(jīng)常有香客問我柬帕,道長哟忍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任陷寝,我火速辦了婚禮锅很,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凤跑。我一直安慰自己爆安,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布仔引。 她就那樣靜靜地躺著鹏控,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肤寝。 梳的紋絲不亂的頭發(fā)上当辐,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音鲤看,去河邊找鬼缘揪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的找筝。 我是一名探鬼主播蹈垢,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼袖裕!你這毒婦竟也來了曹抬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤急鳄,失蹤者是張志新(化名)和其女友劉穎谤民,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疾宏,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡张足,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坎藐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片为牍。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖岩馍,靈堂內(nèi)的尸體忽然破棺而出碉咆,到底是詐尸還是另有隱情,我是刑警寧澤蛀恩,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布吟逝,位于F島的核電站,受9級(jí)特大地震影響赦肋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜励稳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一佃乘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧驹尼,春花似錦趣避、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至地啰,卻和暖如春愁拭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背亏吝。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來泰國打工岭埠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓惜论,卻偏偏與公主長得像许赃,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子馆类,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容