C#,电话数字键盘问题(Mobile Numeric Keypad problem)的算法与源代码

1 电话数字键盘问题

提供移动数字键盘。您只能按向上、向左、向右或向下至当前按钮的按钮。不允许您按最下面一行的角点按钮(即.*和#)。

移动键盘

给定一个数N,找出给定长度的可能数。

示例:

对于N=1,可能的数字数为10(0、1、2、3、...、9)

对于N=2,可能的数字数为36

可能的数字:00、08、11、12、14、22、21、23、25等等。

如果我们从0开始,有效数字将是00、08(计数:2)

如果我们从1开始,有效数字将是11、12、14(计数:3)

如果我们从2开始,有效数字将是22、21、23、25(计数:4)

如果我们从3开始,有效数字将是33、32、36(计数:3)

如果我们从4开始,有效数字将是44,41,45,47(计数:4)

如果我们从5开始,有效数字将是55,54,52,56,58(计数:5)

....................................

....................................

我们需要打印可能的数字。

推荐做法

移动数字键盘

试试看!

N=1是普通情况,可能的数字数为10(0,1,2,3,...,9)

对于N>1,我们需要从某个按钮开始,然后移动到四个方向(向上、向左、向右或向下)中的任何一个,该方向指向有效的按钮(不应转到*、#)。继续这样做,直到获得N个长度编号(深度优先遍历)。

递归解决方案:

移动键盘是4X3的矩形网格(4行3列)

假设Count(i,j,N)表示从位置(i,j)开始的N个长度数字的计数

如果N=1 ,计数(i,j,N)=10

其他的 Count(i,j,N)=所有Count(r,c,N-1)之和,其中(r,c)是新的

长度1从当前有效移动后的位置

位置(i,j)

下面是上述公式的三种实现代码。

2 源代码

cs 复制代码
using System;
using System.Collections;
using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm
{
	public static partial class Algorithm_Gallery
	{
        #region 算法1
		private static int MNKP_Solve_Utility(char[,] keypad, int i, int j, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 1;
			}

			int[] row = { 0, 0, -1, 0, 1 };
			int[] col  = { 0, -1, 0, 1, 0 };

			int totalCount = 0;
			for (int move = 0; move < 5; move++)
			{
				int ro = i + row[move];
				int co = j + col[move];
				if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')
				{
					totalCount += MNKP_Solve_Utility(keypad, ro, co, n - 1);
				}
			}
			return totalCount;
		}

		public static int MNKP_Solve(char[,] keypad, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 10;
			}

			int totalCount = 0;
			for (int i = 0; i < 4; i++) 
			{
				for (int j = 0; j < 3; j++) 
				{
					if (keypad[i, j] != '*' && keypad[i, j] != '#')
					{
						totalCount += MNKP_Solve_Utility(keypad, i, j, n);
					}
				}
			}
			return totalCount;
		}
		#endregion

		#region 算法2
		public static int MNKP_Solve_2th(char[,] keypad, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 10;
			}
			int[] row = { 0, 0, -1, 0, 1 };
			int[] col = { 0, -1, 0, 1, 0 };

			int[,] count = new int[10, n + 1];

			for (int i = 0; i < 10; i++)
			{
				count[i, 0] = 0;
				count[i, 1] = 1;
			}

			for (int k = 2; k <= n; k++)
			{
				for (int i = 0; i < 4; i++) 
				{
					for (int j = 0; j < 3; j++) 
					{
						if (keypad[i, j] != '*' && keypad[i, j] != '#')
						{
							int num = keypad[i, j] - '0';
							count[num, k] = 0;

							for (int move = 0; move < 5; move++)
							{
								int ro = i + row[move];
								int co = j + col[move];
								if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')
								{
									int nextNum = keypad[ro, co] - '0';
									count[num, k] += count[nextNum, k - 1];
								}
							}
						}
					}
				}
			}

			int totalCount = 0;
			for (int i = 0; i < 10; i++)
			{
				totalCount += count[i, n];
			}
			return totalCount;
		}
		#endregion

		#region 算法3
		public static int MNTP_Solve_3th(char[,] keypad, int n)
		{
			if (keypad == null || n <= 0)
			{
				return 0;
			}
			if (n == 1)
			{
				return 10;
			}
			int[] odd = new int[10];
			int[] even = new int[10];

			int useOdd = 0;
			for (int i = 0; i < 10; i++)
			{
				odd[i] = 1;
			}

			for (int j = 2; j <= n; j++)
			{
				useOdd = 1 - useOdd;

				if (useOdd == 1)
				{
					even[0] = odd[0] + odd[8];
					even[1] = odd[1] + odd[2] + odd[4];
					even[2] = odd[2] + odd[1] + odd[3] + odd[5];
					even[3] = odd[3] + odd[2] + odd[6];
					even[4] = odd[4] + odd[1] + odd[5] + odd[7];
					even[5] = odd[5] + odd[2] + odd[4] + odd[8] + odd[6];
					even[6] = odd[6] + odd[3] + odd[5] + odd[9];
					even[7] = odd[7] + odd[4] + odd[8];
					even[8] = odd[8] + odd[0] + odd[5] + odd[7] + odd[9];
					even[9] = odd[9] + odd[6] + odd[8];
				}
				else
				{
					odd[0] = even[0] + even[8];
					odd[1] = even[1] + even[2] + even[4];
					odd[2] = even[2] + even[1] + even[3] + even[5];
					odd[3] = even[3] + even[2] + even[6];
					odd[4] = even[4] + even[1] + even[5] + even[7];
					odd[5] = even[5] + even[2] + even[4] + even[8] + even[6];
					odd[6] = even[6] + even[3] + even[5] + even[9];
					odd[7] = even[7] + even[4] + even[8];
					odd[8] = even[8] + even[0] + even[5] + even[7] + even[9];
					odd[9] = even[9] + even[6] + even[8];
				}
			}

			int totalCount = 0;
			for (int i = 0; i < 10; i++)
			{
				totalCount += (useOdd == 1) ? even[i] : odd[i];
			}
			return totalCount;
		}
        #endregion
    }
}

3 源程序

using System;

using System.Collections;

using System.Collections.Generic;

namespace Legalsoft.Truffer.Algorithm

{

public static partial class Algorithm_Gallery

{

#region 算法1

private static int MNKP_Solve_Utility(char[,] keypad, int i, int j, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 1;

}

int[] row = { 0, 0, -1, 0, 1 };

int[] col = { 0, -1, 0, 1, 0 };

int totalCount = 0;

for (int move = 0; move < 5; move++)

{

int ro = i + row[move];

int co = j + col[move];

if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')

{

totalCount += MNKP_Solve_Utility(keypad, ro, co, n - 1);

}

}

return totalCount;

}

public static int MNKP_Solve(char[,] keypad, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 10;

}

int totalCount = 0;

for (int i = 0; i < 4; i++)

{

for (int j = 0; j < 3; j++)

{

if (keypad[i, j] != '*' && keypad[i, j] != '#')

{

totalCount += MNKP_Solve_Utility(keypad, i, j, n);

}

}

}

return totalCount;

}

#endregion

#region 算法2

public static int MNKP_Solve_2th(char[,] keypad, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 10;

}

int[] row = { 0, 0, -1, 0, 1 };

int[] col = { 0, -1, 0, 1, 0 };

int[,] count = new int[10, n + 1];

for (int i = 0; i < 10; i++)

{

count[i, 0] = 0;

count[i, 1] = 1;

}

for (int k = 2; k <= n; k++)

{

for (int i = 0; i < 4; i++)

{

for (int j = 0; j < 3; j++)

{

if (keypad[i, j] != '*' && keypad[i, j] != '#')

{

int num = keypad[i, j] - '0';

count[num, k] = 0;

for (int move = 0; move < 5; move++)

{

int ro = i + row[move];

int co = j + col[move];

if (ro >= 0 && ro <= 3 && co >= 0 && co <= 2 && keypad[ro, co] != '*' && keypad[ro, co] != '#')

{

int nextNum = keypad[ro, co] - '0';

count[num, k] += count[nextNum, k - 1];

}

}

}

}

}

}

int totalCount = 0;

for (int i = 0; i < 10; i++)

{

totalCount += count[i, n];

}

return totalCount;

}

#endregion

#region 算法3

public static int MNTP_Solve_3th(char[,] keypad, int n)

{

if (keypad == null || n <= 0)

{

return 0;

}

if (n == 1)

{

return 10;

}

int[] odd = new int[10];

int[] even = new int[10];

int useOdd = 0;

for (int i = 0; i < 10; i++)

{

odd[i] = 1;

}

for (int j = 2; j <= n; j++)

{

useOdd = 1 - useOdd;

if (useOdd == 1)

{

even[0] = odd[0] + odd[8];

even[1] = odd[1] + odd[2] + odd[4];

even[2] = odd[2] + odd[1] + odd[3] + odd[5];

even[3] = odd[3] + odd[2] + odd[6];

even[4] = odd[4] + odd[1] + odd[5] + odd[7];

even[5] = odd[5] + odd[2] + odd[4] + odd[8] + odd[6];

even[6] = odd[6] + odd[3] + odd[5] + odd[9];

even[7] = odd[7] + odd[4] + odd[8];

even[8] = odd[8] + odd[0] + odd[5] + odd[7] + odd[9];

even[9] = odd[9] + odd[6] + odd[8];

}

else

{

odd[0] = even[0] + even[8];

odd[1] = even[1] + even[2] + even[4];

odd[2] = even[2] + even[1] + even[3] + even[5];

odd[3] = even[3] + even[2] + even[6];

odd[4] = even[4] + even[1] + even[5] + even[7];

odd[5] = even[5] + even[2] + even[4] + even[8] + even[6];

odd[6] = even[6] + even[3] + even[5] + even[9];

odd[7] = even[7] + even[4] + even[8];

odd[8] = even[8] + even[0] + even[5] + even[7] + even[9];

odd[9] = even[9] + even[6] + even[8];

}

}

int totalCount = 0;

for (int i = 0; i < 10; i++)

{

totalCount += (useOdd == 1) ? even[i] : odd[i];

}

return totalCount;

}

#endregion

}

}

相关推荐
*小雪3 分钟前
uniapp写H5授权登录及分享,返回到目标页面
开发语言·javascript·uni-app
ghie90901 小时前
C#语言中使用“using“关键字的介绍
开发语言·c#
七夜zippoe1 小时前
Java性能调优工具篇:JMH基准测试与Profiler(JProfiler/Async-Profiler)使用指南
java·开发语言·jprofiler·jmh·async-profiler
csdn_wuwt2 小时前
有C#可用的开源的地图吗?
后端·c#·gis·map·开发·设计·地图
6极地诈唬2 小时前
【C#-sqlSugar-sqlite】在Windows从源码编译构建System.Data.SQLite.dll的方法
windows·sqlite·c#
小龙报2 小时前
《嵌入式成长系列之51单片机 --- Keil5创建工程》
c语言·开发语言·c++·单片机·嵌入式硬件·51单片机·学习方法
我只有一台windows电脑2 小时前
C# 对多个任务进行符合管理
c#
无限进步_2 小时前
【C语言】贪吃蛇游戏设计思路深度解析:从零开始理解每个模块
c语言·开发语言·c++·git·游戏·github·visual studio
听风吟丶2 小时前
Java 函数式编程深度实战:从 Lambda 到 Stream API 的工程化落地
开发语言·python
数据的世界012 小时前
JAVA和C#的语法对比
java·windows·c#