蓝桥杯模拟赛——序列计数(记忆化搜索)

题目
【问题描述】
小明想知道,满足以下条件的正整数序列的数量:
1. 第一项为 n;
2. 第二项不超过 n;
3. 从第三项开始,每一项小于前两项的差的绝对值。
请计算,对于给定的 n,有多少种满足条件的序列。
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
【样例输入】
4
【样例输出】
7
【样例说明】
以下是满足条件的序列:
4 1
4 1 1
4 1 2
4 2
4 2 1
4 3
4 4
【评测用例规模与约定】
对于 20% 的评测用例,1 <= n <= 5;
对于 50% 的评测用例,1 <= n <= 10;
对于 80% 的评测用例,1 <= n <= 100;
对于所有评测用例,1 <= n <= 1000。

本人代码:只能通过80%样例 

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll dp[1010][1010];//dp[i][j]表示当前数是i,差的绝对值是j 
ll dfs(ll n,ll cha){
	if(dp[n][cha]>0){
		return dp[n][cha];
	}
	if(cha<=1){
		return 0;
	}
	ll sum=0;
	for(ll nex=cha-1;nex>0;nex--){
		sum=(sum+1+dfs(nex,abs(n-nex)))%10000;
	}
	dp[n][cha]=sum;
	return sum;
}

int main(){
	ll n;
	cin>>n;
	dfs(n,n+1);
	cout<_/___.'  >'"".
//              | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//              \  \ `-.   \_ __\ /__ _/   .-` /  /
//         ======`-.____`-.___\_____/___.-`____.-'======
//                            `=---='
//        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//

 正解:如果我们用f(i,j)表示前一个数是i,当前数是1到j的合法序列的个数;有f(i,j) = 1 + f(i,j-1) + f(j,abs(i-j)-1)即分为两个部分1)i作为前一个数,从1到j-1为当前数的合法序列的个数已经计算好,2)求以j为尾数,后面选择1到abs(i-j)-1的合法序列的个数。

#include 
#include 
#include 
#include 

typedef long long LL;
using namespace std;

int N;
const int MOD = 10000;
int mem[1001][1000];

int dfs(int pre, int cur) {
    if (cur <= 0) return 0;
    if (mem[pre][cur] != 0) return mem[pre][cur];
    return mem[pre][cur] = (1 + dfs(pre, cur - 1) + dfs(cur, abs(pre - cur) - 1)) % MOD;
}

void work() {
    cin >> N;
    cout << dfs(N, N) << endl;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int a = clock();
    work();
    int b = clock();
    clog << (b - a) << endl;
    return 0;
}

 

你可能感兴趣的:(动态规划)