【百度笔试】熊熊全排列

/*********************************************************************************************

度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 '>' 和 '<' )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号即('<'')和n-k-1个大于符号(即'>'),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。

输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子:
5 2
输出例子

66


/*******************************************************************************************************************

思路:这一题初看很容易想到是全排列的问题,能解决,但是会超时。

【注意:本题的特点是什么?什么样的问题用到动态规划?】用动态规划的思路来求解:

dp[i][j] 表示 i 个数字以及 j 个小于号所能表示的数量(相应的,有 i-j-1 个大于号)。而插入 i+1 个数字时,会出现四种情况:

1)加在开头,等于同时加入了一个大于号。(1<2 ==> 3>1<2)

2)加到结尾,等于同时加入了一个小于号。 ( 1<2 ==> 1<2<3 )

3)加到小于号之间,等于同时加入了一个大于号。  (1<2 ==> 1<3>2 )

4)加到大于号之间,等于同时加入了一个小于号。  (2>1 ==> 2<3>1 )

综上所述,dp[i][j]等于以上四种情况之和:
dp[i - 1][j]                                     //将i加在开头等于加入一个大于号,即要求i-1个数时已经有了j个小于号
dp[i - 1][j - 1]                               //将i加在末尾等于加入一个小于号,即要求i-1个数时已经有了j-1个小于号
dp[i - 1][j] * j                                //将i加在任意一个小于号之间,等于加入了一个大于号;即要求i-1个数时已经有了
                                                        j 个小于号,每个小于号都可以进行这样的一次插入
dp[i - 1][j - 1] * (i- j - 1)              //将i加载任意一个大于号之间,等于加入了一个小于号;即要求i-1个数时有了j-1个小
                                                     于号,而此时共有(i-j-1)个大于号。

综上: dp[i][j]=dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j]*j +dp[i-1][j-1](i-j-1);

            dp[i][j]=dp[i-1][j]*(j+1)+dp[i-1][j-1]*(i-j);

//

///

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Solution1{
public:
	int satisfiedNum(){
		int n, k;
		cin >> n >> k;
		vector<vector<int>> dp(n+1, vector<int>(k+1));
		for (int ii = 1; ii <= n; ++ii)
			dp[ii][0] = 1;
		for (int i = 2; i <= n; ++i){
			for (int j = 1; j <=k; ++j){
				dp[i][j] = (dp[i - 1][j - 1] * abs(i - j) + dp[i - 1][j] * (j + 1))%2017;
			}
		}
		return dp[n][k];
	}
};


int main()
{
	Solution1 obj1;
	cout << obj1.satisfiedNum() << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值