算法小玩意

N皇后问题

N*N的棋盘上摆上N个皇后,使皇后不会相互攻击。

public class NQueenPuzzle
{
    private readonly int queenAmount;
    private readonly int[] xLocations;

    private int solutionCount = 0;

    public NQueenPuzzle(int n)
    {
        queenAmount = n;
        xLocations = new int[queenAmount];
    }

    //使用栈求解
    public void Solve_stack()
    {
        Stack<int> lastPos = new Stack<int>(queenAmount);
        lastPos.Push(-1);
        while (lastPos.Count > 0)
        {
            var s = lastPos.Pop();
            for (int i = s + 1; i < queenAmount; i++)
            {
                var k = lastPos.Count;
                xLocations[k] = i;
                if (this.Validate(k))
                {
                    if (k == queenAmount - 1)
                    {
                        this.PrintResult();
                        return;
                    }

                    lastPos.Push(i);
                    lastPos.Push(-1);
                    break;
                }
            }
        }
    }

    //使用递归求解
    public void Solve()
    {
        Stopwatch sw = Stopwatch.StartNew();
        this.Locate(0);
        Console.WriteLine("time cost to solve puzzle: {0:g}", sw.Elapsed);

        if (solutionCount == 0)
        {
            Console.WriteLine("No result for puzzle with {0} queen", queenAmount);
        }
        else
        {
            Console.WriteLine("total {0} result for puzzle with {0} queen", solutionCount, queenAmount);
        }
    }

    private void Locate(int k)
    {
        if (k == queenAmount)
        {
            solutionCount++;
            Console.WriteLine("*** result {0} *****", this.solutionCount);
            this.PrintResult();
            return;
        }


        for (int i = 0; i < queenAmount; i++)
        {
            xLocations[k] = i;

            if (this.Validate(k))
            {
                Locate(k + 1);
            }
        }
    }

    private void PrintResult()
    {
        for (int i = 0; i < this.queenAmount; i++)
        {
            for (int j = 0; j < this.queenAmount; j++)
            {
                Console.Write(j == this.xLocations[i] ? "x " : "- ");
            }

            Console.WriteLine();
        }

        Console.WriteLine();
    }

    private bool Validate(int k)
    {
        bool valid = true;
        for (int j = 0; j < k; j++)
        {
            if (this.xLocations[j] == this.xLocations[k] || Math.Abs(this.xLocations[j] - this.xLocations[k]) == Math.Abs(j - k))
            {
                valid = false;
                break;
            }
        }
        return valid;
    }
}

使用下面的方法输出8皇后解决方案。

NQueenPuzzle puzzle = new NQueenPuzzle(8);
puzzle.Solve();

0-1背包问题

一组宝石,价值对应values,重量对应weight,一个背包最大承重capcity,求怎样选择宝石,可使背包装下价值最多?

public class BagPack0_1
{
    private int[] values;

    private int[] weight;

    private int capcity;

    private int n;

    public BagPack0_1(int[] v, int[] w, int c)
    {
        values = v;
        weight = w;
        capcity = c;
        n = values.Length;
    }

    public void Solve()
    {
        int[,] M = new int[n + 1, capcity + 1];

        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= capcity; j++)
            {
                if (j < weight[i - 1])
                {
                    M[i, j] = M[i - 1, j];
                }
                else
                {
                    M[i, j] = Math.Max(M[i - 1, j], M[i - 1, j - weight[i - 1]] + values[i - 1]);
                }
            }
        }


        Console.WriteLine("max values:{0}", M[n, capcity]);

        this.ShowResult(M, n, capcity);
    }

    private void ShowResult(int[,] M, int i, int j)
    {
        if (i == 0 || j == 0)
        {
            return;
        }
        if (j >= weight[i - 1] && M[i, j] == M[i - 1, j - weight[i - 1]] + values[i - 1])
        {
            this.ShowResult(M, i - 1, j - weight[i - 1]);
            Console.WriteLine("index:{0}, weight:{1}, value:{2} selected ", i, weight[i - 1], values[i - 1]);
        }
        else
        {
            this.ShowResult(M, i - 1, j);
        }
    }

}

测试用例:

int[] w = { 1, 3, 4, 5, 6, 2, 4, 8, 10 };
int[] v = { 4, 2, 1, 10, 12, 2, 30, 40, 10 };
int capacity = 36;
BagPack0_1 bp = new BagPack0_1(v, w, capacity);

bp.Solve();

最大子串问题

两个数组A、B,求最大子串。
public class MaxSubString<T>
{
    private T[] A;

    private T[] B;

    private int m;

    private int n;

    public MaxSubString(T[] A, T[] B)
    {
        this.A = A;
        this.B = B;
        m = A.Length + 1;
        n = B.Length + 1;
    }

    //最大子串引申问题。两个字符串最长相同子串。
    public void Solve_continuous()
    {
        var M = new int[m, n];
        int maxLen = 0;
        int pos = 0;

        for (int i = 1; i < m; i++)
        {
            for (int j = 1; j < n; j++)
            {
                M[i, j] = object.Equals(A[i - 1], B[j - 1]) ? M[i - 1, j - 1] + 1 : 0;
                if (M[i, j] > maxLen)
                {
                    maxLen = M[i, j];
                    pos = i;
                }
            }
        }

        Console.WriteLine("maxLen is:{0}", maxLen);

        for (int i = maxLen; i > 0; i--)
        {
            Console.Write(A[pos - i].ToString() + ",");
        }
    }

    //数组M记录最大子串长度
    public void Solve2()
    {
        var M = new int[m, n];

        for (int i = 1; i < m; i++)
        {
            for (int j = 1; j < n; j++)
            {
                if (object.Equals(A[i - 1], B[j - 1]))
                {
                    M[i, j] = M[i - 1, j - 1] + 1;
                }
                else
                {
                    if (M[i - 1, j] > M[i, j - 1])
                    {
                        M[i, j] = M[i - 1, j];
                    }
                    else
                    {
                        M[i, j] = M[i, j - 1];
                    }
                }
            }
        }

        this.ShowResult2(M, m - 1, n - 1);
        Console.WriteLine();
    }

    private void ShowResult2(int[,] M, int i, int j)
    {
        if (i == 0 || j == 0)
        {
            return;
        }

        if (M[i, j] == M[i - 1, j])
        {
            this.ShowResult2(M, i - 1, j);
        }
        else if (M[i, j] == M[i, j - 1])
        {
            this.ShowResult2(M, i, j - 1);
        }
        else
        {
            this.ShowResult2(M, i - 1, j - 1);
            Console.Write("," + A[i - 1]);
        }
    }

    //使用辅助数组S,记录数组元素是否是最大子串成员
    public void Solve1()
    {
        int[,] M = new int[m, n];
        int[,] S = new int[m, n];//1left,2up,3select

        for (int i = 0; i < m; i++)
        {
            M[i, 0] = 0;
        }
        for (int i = 0; i < n; i++)
        {
            M[0, i] = 0;
        }

        for (int i = 1; i < m; i++)
        {
            for (int j = 1; j < n; j++)
            {
                if (object.Equals(A[i - 1], B[j - 1]))
                {
                    M[i, j] = M[i - 1, j - 1] + 1;
                    S[i, j] = 3;
                }
                else
                {
                    if (M[i - 1, j] > M[i, j - 1])
                    {
                        M[i, j] = M[i - 1, j];
                        S[i, j] = 1;
                    }
                    else
                    {
                        M[i, j] = M[i, j - 1];
                        S[i, j] = 2;
                    }
                }
            }
        }

        Console.WriteLine("Max sub list count:{0}", M[m - 1, n - 1]);

        ShowResult(S, m - 1, n - 1);
        Console.WriteLine();
    }

    private void ShowResult(int[,] S, int i, int j)
    {
        if (i == 0 || j == 0)
        {
            return;
        }

        if (S[i, j] == 3)
        {
            ShowResult(S, i - 1, j - 1);
            Console.Write("," + A[i - 1]);
        }
        else if (S[i, j] == 1)
        {
            ShowResult(S, i - 1, j);
        }
        else if (S[i, j] == 2)
        {
            ShowResult(S, i, j - 1);
        }
    }

}

测试:

int[] A = new[] { 1, 2, 3, 4 };
int[] B = { 1, 2, 1, 2, 3, 4 };

MaxSubString<int> mss = new MaxSubString<int>(A, B);
mss.Solve1();

posted on 2016-04-27 14:22  ShaunLing  阅读(214)  评论(0编辑  收藏  举报