物以稀为贵

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  时间复杂度和空间复杂度?

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);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值