当前位置: 首页 > 知识库问答 >
问题:

四色图定理递归回溯算法

戈曾琪
2023-03-14

我编写了以下程序来递归地实现四色地图定理(简而言之,任何地图只能用4种颜色着色,而没有任何相邻区域是相同的颜色)。一切都在编译,但是我的输出给我错误的数据(每个区域的颜色为-1,而不是现在的值0-3)。我最大的问题是为什么输出不正确。

对于那些想知道的人来说,输入文件是一个邻接矩阵,看起来如下所示:

0 1 0 1  
1 0 1 0  
0 1 0 1  
1 0 1 0  

这是我的代码:

public class FourColorMapThm 
{
    public static boolean acceptable(int[] map, int[][] matrix, int r, int c)
    {
        for(int i = 0; i < map.length; i++)
        {
            if(matrix[r][i] == 1)
            {
                if(map[i] == c) return false;
            }
        }
        return true;
    }

    public static boolean colorTheMap(int[] map, int[][] matrix, int r, int c)
    {
        boolean q = false;
        int i = 0;

        if(!acceptable(map, matrix, r, i)) return false;

        map[r] = i;
        boolean done = true;

        for(int j = 0; j < map.length; j++)
        {
            if(map[j] == -1)
            {
                done = false;
            }
        }
        if(done) return true;

        do
        {
            i++;
            q = colorTheMap(map, matrix, r+1, i);
            if(q) return true;
        }
        while(i <= 3);

        map[r] = -1;
        return false;
    }

    public static void main(String[] args) throws IOException
    {
        Scanner in = new Scanner(System.in);
        String snumRegions, fileName;
        int numRegions;

        System.out.print("Enter the number of regions: ");
        snumRegions = in.nextLine();
        numRegions = Integer.parseInt(snumRegions);

        System.out.print("\nEnter filename for adjacency matrix: ");
        fileName = in.nextLine();
        in.close();

        Scanner inFile = new Scanner(new FileReader(fileName));
        PrintWriter outFile = new PrintWriter("coloredMap.txt");
        int[][] matrix = new int[numRegions][numRegions];
        int[] map = new int[numRegions];

        //initializing matrix from file
        for(int row = 0; row < matrix.length; row++)
        {
            for(int col = 0; col < matrix.length; col++)
            {
                matrix[row][col] = inFile.nextInt();
            }
        }
        inFile.close();

        //initialize map vals to -1
        for(int i = 0; i < map.length; i++)
        {
                map[i] = -1;
        }

        colorTheMap(map, matrix, 0, 0);

        outFile.println("Region\t\tColor");
        for(int i = 0; i < map.length; i++)
        {
            outFile.println(i+1 + "\t\t" + map[i]);
        }
        outFile.close();
    }
}

共有1个答案

杭曦
2023-03-14

您没有在Color TheMap中使用c,并且您可能想要这样做。

您获得包含所有条目的-1地图的原因如下:

    int i = 0;
    if(!acceptable(map, matrix, r, i)) return false;
    map[r] = i;
    .
    .
    .
    do
    {
        i++;
        q = colorTheMap(map, matrix, r+1, i);
        if(q) return true;
    }
    while(i <= 3);
    map[r] = -1;

每次调用colorTheMap(map,matrix,r1,i)都会在点击时返回false

    int i = 0;
    if(!acceptable(map, matrix, r, i)) return false;

如果它的任何一个邻居已经用0(因为你从来没有使用c,你总是会在map[r]=i中将0分配给map[r];如果你到达那一行,所以在返回后,我们会立即返回false,然后再将任何颜色分配给r。我假设你的输入图是连接的,所以任何调用colorTheMap(map,matrix,r,c)都会找到r的一个邻居,用0着色,甚至不会将map[r]设置为任何其他内容,因为if(!acceptable(map,matrix,r,I))返回false将立即返回,或者它只在

    do
    {
        i++;
        q = colorTheMap(map, matrix, r+1, i);
        if(q) return true;
    }
    while(i <= 3);

并撤消循环之后的map[r]=-1;行中的着色。

另一个注意事项:我假设你试图实现贪婪的着色,但这不是最佳的,也就是说,你可能会以这种方式得到未着色的区域。四色问题比简单的“用一个没有相邻颜色的颜色给任何东西着色,你就很好”要复杂得多,否则就不会花一个多世纪的时间来证明四种颜色就足够了。以下是一个需要二次时间的正确算法的大纲(在链接丢失的情况下引用:尼尔·罗伯逊、丹尼尔·桑德斯、保罗·西摩和罗宾·托马斯。1996年。有效的四色平面图。载于第二十八届计算理论年度ACM研讨会(STOC'96)。国际计算机学会,美国纽约州纽约市,571-575。DOI:https://doi.org/10.1145/237814.238005)。它出现在证明四个着色平面图总是可能的20年后。

 类似资料:
  • 目前的问题是,将一张地图分成邻接矩阵中表示的区域,并使用四种颜色对地图进行着色,以确保没有两个相邻区域共享相同的颜色。我们将使用邻接矩阵来编码哪个区域与哪个其他区域相邻。矩阵的列和行是区域,如果两个区域不相邻,则单元格包含0,如果两个区域相邻,则单元格包含1。创建一个递归回溯解决方案,该方案接受用户的交互输入,即地图中的区域数和表示地图组成的邻接矩阵的文件名。 问题是,我遇到的是,第一个值在国家颜

  • 我正在开发高级培养皿网络编辑器/模拟器。首先,这里有一些词汇 圆圈=位置 矩形=过渡 就地整数 = 标记 过渡状态=防护 我被困在通过过渡的守卫。守卫是一个条件,如果你想执行转换,这需要是真的。我知道我应该以某种方式使用回溯,但我不知道在程序开始之前进入过渡的位置数,所以我不能使用循环,因为我不知道我需要多少个循环。 所以,我想从第一位获取第一个令牌,从第二位获取第一令牌,然后尝试通过守卫,如果通

  • 我正在为suduko解算器编写一个递归回溯算法。看起来suduko的情况很糟糕。 代码: s是由节点对象组成的。每个节点对象都有一个(x, y)表示板子,一个值,它可以是一个数字,也可以是一个没有赋值的句点,还有一个平方值(suduko的平方是多少)。 我知道,我的方法和都有效检查棋盘是否正确求解,检查如果suduko游戏的约束条件成立,我是否将给定的节点设置为给定棋盘上的给定值。 出于某种原因,

  • 我的问题是,当一个9不能正确添加时,该方法会中断。不知何故,我不知道如何让它回到前一点,并向上数,这将创建一个新的“路径”,所以我想如果我做对了,一切都应该很好。我仍然在使用递归:-/ 正如我所知,我认为Sudokurecrect()做了它应该做的事情。编辑:您可以忽略布尔测试。我知道我不使用它,我试着想一些东西,但显然我不知道如何使用它。 输出为 在那之后,不管检查哪个变体。所以问题是一样的。

  • 我对编码还是很陌生的,我正在尝试一些稍微困难的主题,例如修改数独递归回溯程序的解决方案。最初的解决方案是针对大小为3x3的数独,我希望我的解决方案可以与正常大小的数独(9x9)一起使用。3x3解决方案在这里找到。 我觉得我对算法非常了解:对于网格中的每个列表(包含该单元格的可能值),在每一步尝试每个数字,确保电路板仍然有效,移动到下一个列表,分配一个可能的数字直到其有效,等等。如果当前电路板不正确

  • 我正在创建一个递归导航迷宫的程序。代码: 然而,每当我到达死胡同时,它都不会回溯。当我调试时,它表明当程序从递归或“回溯”返回时,我的起始值专注于停留在我的死胡同空间。 例如: 9是我的出发点。2是我的退出。4是我的道路。1 表示墙壁。当我到达一个死胡同时(在本例中为第 7 行,第 2 列)。我的立场是等于整个程序其余部分的死胡同空间。这是为什么呢?