算法设计与分析: 1-4 金币阵列问题

1-4 金币阵列问题


问题描述

有m*n枚金币在桌面上排列成一个m行n列的金币阵列。每一枚金币或正面朝上,或背面朝上。用数字表示金币状态,0表示正面朝上,1表示背面朝上。

金币阵列游戏的规则是:
(1)每次将任一行金币翻过来放在原来的位置上。
(2)每次可以任选2列,交换这2列金币的位置。

任务:给定金币的初始状态和目标状态,编程计算按金币游戏规则,将金币排列从初始状态变换到目标状态所需的最少变换次数。


Java

public class Main {
    //case 1
    private static int[][] source = {{1, 0, 1}, {0, 0, 0}, {1, 1, 0}, {1, 0, 1}};
    private static int[][] target = {{1, 0, 1}, {1, 1, 1}, {0, 1, 1}, {1, 0, 1}};
    //case 2
//    private static int[][] source = {{1, 0, 1}, {0, 0, 0}, {1, 0, 0}, {1, 1, 1}};
//    private static int[][] target = {{1, 1, 0}, {1, 1, 1}, {0, 1, 1}, {1, 0, 1}};

    private static int[][] tempMatrix = new int[4][3];

    private static int rows = 4;
    private static int columns = 3;
    private static int count, best=9999;

    public static void main(String[] args) {
        int i, j, k;

        /*思路:一、首先将每一列运用列交换作为第1列,
               二、然后对每一行进行判断,如果元素与目标元素不相等,则进行行翻转处理,
               三、最后向后判断后面列是否相同*/

        //一、每一列运用列交换作为第1列
        for(k=0; k<columns; k++){

            for(i=0; i<rows; i++)
                for(j=0; j<columns; j++)
                    tempMatrix[i][j] = source[i][j];

            count = 0;
            exchangeColumns(0, k);

            //二、对每一行进行判断,如果元素与目标元素不相等,则进行行翻转处理
            for(i=0; i<rows; i++){
                if(tempMatrix[i][0] != target[i][0])
                    turnoverRow(i);
            }

            //三、向后判断后面列是否相同
            boolean found = true;
            for(i=0; i<columns; i++){
                found = false;

                //1 先判断tempMatrix当前列是否与目标矩阵的当前列相同
                if(isSameColumns(i, i)){
                    found = true;
                    continue;
                }

                //2 tempMatrix当前列与目标矩阵的当前列不相同时,看tempMatrix当前列之后的列是否与目标矩阵当前列相同
                //  1)若之后有相同的列,则进行列交换操作,继续比较后面的列
                //  2)若之后也没有相同的列,则说明此次变换不能变换成目标矩阵,进行下一种变换尝试
                for(j=i+1; j<columns; j++){
                    if(isSameColumns(i, j)){
                        exchangeColumns(i, j);
                        found = true;
                        break;
                    }
                }

                if(!found)
                    break;
            }

            if(found)
                best = (count < best) ? count : best;
        }

        if(best < 9999)
            System.out.println("At least "+best+" steps needed to change source to target!");
        else
            System.out.println("Can not change source to target!");
    }

    //turnover one row
    private static void turnoverRow(int i){
        for(int j=0; j<columns; j++)
            tempMatrix[i][j] = 1-tempMatrix[i][j];

        count++;
    }

    //exchange two columns
    private static void exchangeColumns(int i, int j){
        if(i == j)
            return;

        for(int k=0; k<rows; k++){
            int tempValue = tempMatrix[k][i];
            tempMatrix[k][i] = tempMatrix[k][j];
            tempMatrix[k][j] = tempValue;
        }

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

    //check whether two columns are same
    private static boolean isSameColumns(int i, int j){
        boolean isSame = true;

        for(int k=0; k<rows; k++){
            if(target[k][i] != tempMatrix[k][j]){
                isSame = false;
                break;
            }
        }

        return isSame;
    }
}

Case 1 output

At least 2 steps needed to change source to target!

Case 2 output

Can not change source to target!

Reference

王晓东《计算机算法设计与分析》(第3版)P7-8

猜你喜欢

转载自blog.csdn.net/ioio_/article/details/80945597