backtracking n staircases at most k steps in a single jump

一曲冷凌霜 提交于 2019-12-02 04:09:46

One huge problem is in the code below: you deduct the quantity of steps for each possibility within the step range.

n=n-i
res=CSR(n,i,res)

When you're done exploring what you can do with a 1-step jump, you need to backtrack and try from the same starting point (this instance's original value of n) with a 2-step jump. Change the code to:

res = CSR(n-i, i, res)

This keeps the n value intact as you go through the loop.

In addition, you can't limit future jumps to the max of what you just took. Change that second parameter, too:

res = CSR(n-i, k, res)

That should get you moving. Also try this lovely debug blog for help. At least insert one or two tracing statements, such as

print n, k, res

at the top of your routine.

CAVEAT

This is not all of your trouble. The largest remaining problem is that CSR returns only one solution: every step you take is appended to the same list. You need a way to gather the completed solutions as separate lists; the append in climbingStaircase is executed only once, after CSR is entirely finished.

You need to recognize a completed solution at n==0.

DEBUGGING HELP

Here is a version of your program with the recursion parameters fixed, and debugging traces inserted.

indent = ""

def climbingStaircase(n, k):
    final_res = []
    final_res.append(CSR(n, k, []))
    return final_res

def CSR(n, k, res):
    global indent
    indent += "  "
    print indent, n, k, res
    if n == 0:
        print "SOLUTION", res
    else:
        for i in range(1, k+1):
            if n-i >= 0:
                CSR(n-i, k, res + [i])
    indent = indent[:-2]

print climbingStaircase(4, 2)

Note the use of "indent" to help visualize your recursion and backtracking. The critical part here is that, instead of updating res globally, I've left it as a local variable. I've also removed the return value for now, simply dumping to output the solutions as they're found. You can see how it works:

   4 2 []
     3 2 [1]
       2 2 [1, 1]
         1 2 [1, 1, 1]
           0 2 [1, 1, 1, 1]
SOLUTION [1, 1, 1, 1]
         0 2 [1, 1, 2]
SOLUTION [1, 1, 2]
       1 2 [1, 2]
         0 2 [1, 2, 1]
SOLUTION [1, 2, 1]
     2 2 [2]
       1 2 [2, 1]
         0 2 [2, 1, 1]
SOLUTION [2, 1, 1]
       0 2 [2, 2]
SOLUTION [2, 2]
[None]

With this stuff in place, I'm hopeful you can trace your logic and figure out how to capture the sequence of solutions at a level of your choosing.

Successfully implemented Prune's answer.

def climbingStaircase(n, k):
    res=[]
    CSR(n,k,[],res)
    return res

def CSR(n,k,str_, res):
    if n == 0:
        res.append(str_)
    else:
        for i in range(1,k+1):
            if n-i>=0:
                CSR(n-i,k,str_+[i],res)

A quick Java version of this solution:

int[][] climbingStaircase(int n, int k) {
    List<ArrayList<Integer>> list = new ArrayList<>();
    climb(n, k, new ArrayList<Integer>(), list);

    // convert to int[][]
    int[][] result = new int[list.size()][];
    for (int i=0; i<list.size(); i++) {
        List<Integer> l = list.get(i); 
        int [] arr = new int[l.size()];
        for (int j=0; j<l.size(); j++)
            arr[j] = l.get(j);
        result[i] = arr;
    }
    return result;
}
void climb(int n, int k, ArrayList<Integer> prev, List<ArrayList<Integer>> list) {
    if (n==0) { // no more stairs, done climbing
        list.add(prev);
    } else {
        for (int i=1; i<=k; i++) { // climb remaining stairs in intervals from 1 to k steps
            if (i <= n) { // no need to test intervals larger than remaining # of stairs
                ArrayList<Integer> branch = new ArrayList<>(prev);
                branch.add(i);
                climb(n-i, k, branch, list);
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!