我如何完成这个双向匹配程序?

How do I complete this BiPartite Matching program?

我正在为 class 做作业,我必须读取邻接矩阵并在 Java 中输出二分匹配。我已经获得了两种填写方法来完成此操作,并且我已经设法让它适用于一个用例,但我在让它适用于其他两个用例时遇到了一些麻烦。我将在下面粘贴我的源代码。程序开头有 3 个测试用例,每个测试用例的预期输出显示在结尾处。

我需要将矩阵实现为二维字符数组。我遇到的问题似乎与它的回溯部分有关。第二个测试用例 returns 结果正确。如果有人可以帮助我理解我做错了什么,我将不胜感激。我寻找匹配的过程是:

  1. 从最后一行开始
  2. 遍历每一列
  3. 如果该列标记为 Y 且该列当前未被占用(标记为 'T'),则将该列标记为已占用 'T'。
  4. 为下一行递归调用方法
  5. 遍历矩阵,显示匹配

    public class BiPartiteMatch
    {
    // **************** main  ****************
    public static void main(String[] args)
    {
        System.out.println("Case 1: No matching exists. \n");
    
        //                     a    b    c    d    e    No matching A, C, E
        //                    -----------------------   will only take a & d 
        char [][]M = { /*E*/ {'y', 'n', 'n', 'y', 'n'},
                       /*D*/ {'n', 'y', 'n', 'y', 'n'},
                       /*C*/ {'y', 'n', 'n', 'y', 'n'},
                       /*B*/ {'y', 'n', 'y', 'y', 'y'},
                       /*A*/ {'y', 'n', 'n', 'y', 'n'} };
    
    
        System.out.println("Case 2: Matching with no backtracking needed. \n"); 
    
        //                     a    b    c    d    e    Matching with no 
        //                    -----------------------   backtracking needed
        char [][]M = { /*E*/ {'y', 'n', 'n', 'y', 'y'},
                       /*D*/ {'n', 'y', 'n', 'y', 'n'},
                       /*C*/ {'n', 'y', 'y', 'n', 'n'},
                       /*B*/ {'y', 'n', 'y', 'n', 'n'},
                       /*A*/ {'n', 'y', 'n', 'n', 'y'} };
    
    
        System.out.println("Case 3: Matching with backtracking. \n");
    
        //                     a    b    c    d    e    Matching with 
        //                    -----------------------   backtracking
        char [][]M = { /*E*/ {'n', 'y', 'n', 'n', 'y'},
                       /*D*/ {'y', 'n', 'y', 'n', 'n'},
                       /*C*/ {'n', 'y', 'y', 'n', 'n'},
                       /*B*/ {'n', 'y', 'n', 'y', 'n'},
                       /*A*/ {'y', 'n', 'n', 'y', 'y'} };
    
    
     if (findMatch(M, M.length-1)) // Find matches starting with the last row
         displayMatches(M); 
     else
         System.out.println("There is no matching.");         
    
    }// end main
    
    
    
    // **************** recursive findMatch  ****************
    public static boolean findMatch(char [][]M, int myRow)
    {           
            if(myRow < 0)
                return false;            
    
            for(int c = 0; c < M.length; c++)
            {
                if(M[myRow][c] == 'y' && !isTaken(M, myRow, c))
                {
                    M[myRow][c] = 't';
                    break;
                }
            }
    
            findMatch(M, myRow-1);
    
            return true;
    
    }// end findMatch      
    
    
    // **************** isTaken  ******************
    // *******is this column already taken? ********
    public static boolean isTaken(char [][]M, int row_Im_In, int col_Im_In)
    {
            for(int r = row_Im_In+1; r < M.length; r++)
            {
                if(M[r][col_Im_In] == 't')
                    return true;
            }
    
            return false;
    
    }// end isTaken
    
    
    // **************** displayMatches  ****************
    public static void displayMatches(char [][]M)
    {
        final char []MatchFrom = {'E', 'D', 'C', 'B', 'A'};
        final char []MatchTo   = {'a', 'b', 'c', 'd', 'e'};
    
                for(int r = M.length-1; r > -1; r--)
                {
                    for(int c = 0; c < M.length; c++)
                    {
                        if(M[r][c] == 't')
                        {
                            System.out.println(MatchFrom[r] + " matches to " + MatchTo[c]);
                        }
                    }
                }
    
    
    }// end displayMatches
    
    }// end class declaration
    

预期结果:

Case 1: No mathing exists. 

There is no matching.


Case 2: Matching with no backtracking needed. 

A matches to b
B matches to a
C matches to c
D matches to d
E matches to e


Case 3: Matching with backtracking. 

A matches to a
B matches to d
C matches to b
D matches to c
E matches to e

您需要将 findMatch 替换为如下内容:

public static boolean findMatch(char [][]M, int myRow)
{           
        if(myRow < 0)
            return true;            

        for(int c = 0; c < M.length; c++)
        {
            if(M[myRow][c] == 'y' && !isTaken(M, myRow, c))
            {
                M[myRow][c] = 't';
                if (findMatch(M, myRow-1))
                    return true;
                M[myRow][c] = 'y';
            }
        }
        return false;

}

目前,您的代码只会尝试为每个元素找到第一个可能的匹配项。

要进行正确的回溯,您需要从循环内部调用递归函数,然后如果找不到完全匹配,您需要测试下一个位置。