算法小玩意
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();