1 2 3
4 5 6
7 8 9
0
说某移动电信运营商开发了一个名为“争霸”的游戏,为鼓励用户参与,凡签约用户均可获得前三位为888的手机号码,但这样的话就有10的8次方种可能,现在给出一种限制条件减少号码数量,就是两个相邻号码之间的关系必须满足象棋里的“将步”
即:给你前三位都是888 后面8位是上面的数字 每个数的相邻只有有限个数字
比如8881* 那么与1相邻的只可以是2和4
888812那么与2相邻的只可以是1,5,3 就是这个意思
如果选择5 那么可以选择的有2,4,6,8
问:
1 用什么算法比较好?为什么?
2 最优的算法是什么?为什么?
3 用什么数据结构最好?为什么?
4 时间复杂度和空间复杂度?
4 5 6
7 8 9
0
说某移动电信运营商开发了一个名为“争霸”的游戏,为鼓励用户参与,凡签约用户均可获得前三位为888的手机号码,但这样的话就有10的8次方种可能,现在给出一种限制条件减少号码数量,就是两个相邻号码之间的关系必须满足象棋里的“将步”
即:给你前三位都是888 后面8位是上面的数字 每个数的相邻只有有限个数字
比如8881* 那么与1相邻的只可以是2和4
888812那么与2相邻的只可以是1,5,3 就是这个意思
如果选择5 那么可以选择的有2,4,6,8
问:
1 用什么算法比较好?为什么?
2 最优的算法是什么?为什么?
3 用什么数据结构最好?为什么?
4 时间复杂度和空间复杂度?
5 一共有多少种情况?
最好的方法是DP。一个位置上的数字出现的可能性为其前一位置(低位置)出现的能与其相邻的数字可能性之和。
dp[i][j]表示号码的第i位用j这个数字时的号码可取的总数;
dp[i][j]=dp[i-1][k]之和(k表示可以与j相邻的数字)
实现代码如下:
#include <iostream>
using namespace std;
// 1 2 3
// 4 5 6
// 7 8 9
// 0
int a[2][10] = {{1,1,1,1,1,1,1,1,1,1}};
int main()
{
int* src=a[0];
int* dst=a[1];
for( int i = 1; i < 8; ++i )
{
dst[0] = src[8];
dst[1] = src[2] + src[4];
dst[2] = src[1] + src[3] + src[5];
dst[3] = src[2] + src[6];
dst[4] = src[1] + src[5] + src[7];
dst[5] = src[2] + src[4] + src[6] + src[8];
dst[6] = src[3] + src[5] + src[9];
dst[7] = src[4] + src[8];
dst[8] = src[0] + src[5] + src[7] + src[9];
dst[9] = src[6] + src[8];
swap(src,dst);
}
int sum = 0;
for( int i = 0; i < 10; ++i )
{
sum += src[i];
}
cout << "sum= " << sum << endl;
}
输出 sum= 14826
real time = 0.003s
user time = 0.002s
final int[][] map = {
{ 8 }, { 2, 4 }, { 1, 3, 5 }, { 2, 6 }, { 1, 5, 7 },
{ 2, 4, 6, 8 }, { 3, 5, 9 }, { 4, 8 },
{ 0, 5, 7, 9 }, { 6, 8 } };
final int[][] res = new int[10][7];
int sum = 0;
for (int i = 0; i < 7; i++)
for (int j = 0; j < 10; j++)
if (i == 0)
sum += res[j][i] = map[j].length;
else {
for (int n : map[j])
res[j][i] += res[n][i - 1];
sum += res[j][i];
}
System.out.println(sum);