Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 动态规划还是回溯?_Algorithm_Dynamic Programming_Backtracking - Fatal编程技术网

Algorithm 动态规划还是回溯?

Algorithm 动态规划还是回溯?,algorithm,dynamic-programming,backtracking,Algorithm,Dynamic Programming,Backtracking,我的朋友给了我以下问题: Input: A matrix of letters and a word. Output: The frequency of the word in the matrix assuming you can move left, right, up and down in the matrix to form the word. 例如: Input: S E X Y A S E A A A X A A A Y A And word is SEXY. Output

我的朋友给了我以下问题:

Input: A matrix of letters and a word.
Output: The frequency of the word in the matrix assuming
  you can move left, right, up and down in the matrix to form the word.
例如:

Input:
S E X Y
A S E A
A A X A
A A Y A
And word is SEXY.

Output:
4 (four times in matrix of letters)
这是我解决问题的代码:

package backtracking;

public class CountFrequency {
    private char[][] matrixOfLetter;
    private String word;
    private int n, m;
    private int lengthOfWord;
    private int[][] matrixCountFrequency;

    public CountFrequency(int n, int m, String word) {
        matrixOfLetter = new char[n][m];
        this.word = word;
        this.n = n;
        this.m = m;
        this.lengthOfWord = word.length();

        matrixCountFrequency = new int[n][m];
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                matrixCountFrequency[i][j] = 0;
    }

    public static void main(String[] args) {
        CountFrequency countFrequency = new CountFrequency(4, 4, "SEXY");

        countFrequency.addMatrixOfLetter(0, 0, 'S');
        countFrequency.addMatrixOfLetter(0, 1, 'E');
        countFrequency.addMatrixOfLetter(0, 2, 'X');
        countFrequency.addMatrixOfLetter(0, 3, 'Y');
        countFrequency.addMatrixOfLetter(1, 0, 'A');
        countFrequency.addMatrixOfLetter(1, 1, 'S');
        countFrequency.addMatrixOfLetter(1, 2, 'E');
        countFrequency.addMatrixOfLetter(1, 3, 'A');
        countFrequency.addMatrixOfLetter(2, 0, 'A');
        countFrequency.addMatrixOfLetter(2, 1, 'A');
        countFrequency.addMatrixOfLetter(2, 2, 'X');
        countFrequency.addMatrixOfLetter(2, 3, 'A');
        countFrequency.addMatrixOfLetter(3, 0, 'A');
        countFrequency.addMatrixOfLetter(3, 1, 'A');
        countFrequency.addMatrixOfLetter(3, 2, 'Y');
        countFrequency.addMatrixOfLetter(3, 3, 'A');

        countFrequency.process();
        countFrequency.printResult();
    }

    public void addMatrixOfLetter(int i, int j, char c) {
        matrixOfLetter[i][j] = c;
    }

    public void process() {
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j) {
                if (word.indexOf(matrixOfLetter[i][j]) == -1) {
                    matrixCountFrequency[i][j] = -1;
                    continue;
                }
                if (matrixOfLetter[i][j] == word.charAt(lengthOfWord - 1))
                    processWithLastChar(lengthOfWord - 1, i, j);
            }
    }

    public void processWithLastChar(int indexOfWord, int row, int col) {
        matrixCountFrequency[row][col] += 1;
        if (indexOfWord == 0)
            return;
        else {
            if (row - 1 >= 0) {
                if (matrixOfLetter[row - 1][col] == word
                        .charAt(indexOfWord - 1))
                    processWithLastChar(indexOfWord - 1, row - 1, col);
            }

            if (row + 1 < lengthOfWord) {
                if (matrixOfLetter[row + 1][col] == word
                        .charAt(indexOfWord - 1))
                    processWithLastChar(indexOfWord - 1, row + 1, col);
            }

            if (col - 1 >= 0) {
                if (matrixOfLetter[row][col - 1] == word
                        .charAt(indexOfWord - 1))
                    processWithLastChar(indexOfWord - 1, row, col - 1);
            }

            if (col + 1 < lengthOfWord) {
                if (matrixOfLetter[row][col + 1] == word
                        .charAt(indexOfWord - 1))
                    processWithLastChar(indexOfWord - 1, row, col + 1);
            }
        }
    }

    public void printResult() {
        int count = 0;
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < m; ++j) {
                if (word.charAt(0) == matrixOfLetter[i][j])
                    count += matrixCountFrequency[i][j];
            }

        System.out.println("Frequency is : " + count);
    }
}
我使用了回溯算法,但我只在看到单词的最后一个字母时回溯,在看到单词中大部分字母正确时再次回溯

我使用计数器矩阵来计算字母的频率

这个问题能用动态规划算法解决吗


或者有更好的想法吗?

可以用动态规划来解决,我认为这是最容易理解的解决方案

创建一个平行的三维矩阵。如果字母矩阵的维数为nxm,且搜索的单词长度为L个字母,则创建矩阵dp[n][m][L]。在dp[i][j][k]中,您存储了您发现的将字母首字母[i][j]用作单词第k个字母的方法

你有dp[i][j][k]=sumdp[i+delta1][j+delta2][k+1],其中{delta1,delta2}在{0,1},{0,-1},{1,0},{-1,0}中。递归的底部是delta[i][j][L-1]=初始[i][j]==单词[L-1]

如果将所有可能的i和j的dp[i][j][l-1]相加,则给出最终结果

希望这对你有帮助

编辑

我必须承认我在最初的解决方案中做了一个愚蠢的提议。我提出的动态解决方案没有考虑我使用的字母。因此,对于矩阵

XXXX
XABX
XXXX
字符串ABAB my algorithm将返回一个计数-从a到B,然后返回到a,再返回到B。这对于您所需要的可能是错误的

遗憾的是,跟踪您已经访问过的内容在动态方法中并不简单,现在我开始认为回溯更适合您的问题


顺便说一句,您在解决方案中也没有考虑到这一点,但是在回溯过程中跟踪您访问的内容要容易得多。我还认为回溯将在内存和性能方面更加有效。

它可以用动态规划来解决,我认为这是最容易理解的解决方案

创建一个平行的三维矩阵。如果字母矩阵的维数为nxm,且搜索的单词长度为L个字母,则创建矩阵dp[n][m][L]。在dp[i][j][k]中,您存储了您发现的将字母首字母[i][j]用作单词第k个字母的方法

你有dp[i][j][k]=sumdp[i+delta1][j+delta2][k+1],其中{delta1,delta2}在{0,1},{0,-1},{1,0},{-1,0}中。递归的底部是delta[i][j][L-1]=初始[i][j]==单词[L-1]

如果将所有可能的i和j的dp[i][j][l-1]相加,则给出最终结果

希望这对你有帮助

编辑

我必须承认我在最初的解决方案中做了一个愚蠢的提议。我提出的动态解决方案没有考虑我使用的字母。因此,对于矩阵

XXXX
XABX
XXXX
字符串ABAB my algorithm将返回一个计数-从a到B,然后返回到a,再返回到B。这对于您所需要的可能是错误的

遗憾的是,跟踪您已经访问过的内容在动态方法中并不简单,现在我开始认为回溯更适合您的问题


顺便说一句,您在解决方案中也没有考虑到这一点,但是在回溯过程中跟踪您访问的内容要容易得多。我还认为回溯将在内存和性能方面更加有效。

非常感谢!“我想用三维矩阵来解决动态规划问题,但我不能把它变成现实。”特朗霍恩,很遗憾,我纠正了我的答案,证明我错了。请看一看,我认为回溯的复杂性是Omn,和动态规划一样。实际上,我可以通过为我访问的mark元素添加一些flags变量来加快速度。我会仔细研究你的解决方案。@TrungHuynh如果你不需要重复这些字母,回溯的复杂性会更好。最坏情况下,实际复杂性为Om*n*3^mn。而dyp解决方案将更加糟糕。然而,如果你可以重复这些,动态解决方案将具有Omnl复杂性:@TrungHuynh我可以为此做动态解决方案,没有问题。问题是状态非常复杂——它必须携带所有已经使用过的字母。使用这种解决方案,在处理过程中不会多次访问任何状态。这使dp变得毫无意义。这就是为什么我告诉你回溯会更有效率。非常感谢!“我想用三维矩阵来解决动态规划问题,但我不能把它变成现实。”特朗霍恩,很遗憾,我纠正了我的答案,证明我错了。请看一看,我认为回溯的复杂性是Omn,和动态规划一样。实际上,我可以通过为我访问的mark元素添加一些flags变量来加快速度。我会仔细研究你的解决方案。@TrungHuynh如果你不需要重复这些字母,回溯的复杂性会更好。实际薪酬
lexity是Om*n*3^mn最坏的情况。而dyp解决方案将更加糟糕。然而,如果你可以重复这些,动态解决方案将具有Omnl复杂性:@TrungHuynh我可以为此做动态解决方案,没有问题。问题是状态非常复杂——它必须携带所有已经使用过的字母。使用这种解决方案,在处理过程中不会多次访问任何状态。这使dp变得毫无意义。这就是为什么我告诉你回溯会更有效率。