URAL 1017 Staircases 记忆化搜索

来源:互联网 发布:动态ppt制作软件 编辑:程序博客网 时间:2024/05/24 06:48

终于刷了道还算上的了台面的题了 . . . . . .

给你N个方块,让你排成M(M  >=  2)列,每列的块数Si要满足(Si < Si+1,Si >=1)。问一共有多少种排列方案。

首先需要预处理出排成M列所需要的最少的块数,即 pre[ M ] = 1 + 2 + 3 +  ... + M-1 + M。

然后对于确定的N,M的取值需满足 2 <= M  &&  pre[M] <= N。

设 M 的最大取值为Max。

然后我们计算出把 N-pre[ i ] 放到 i (i∈[2,Max] )列的情况就可以了,放得时候要满足题目的大前提。

话说记忆化搜索好唬人哇。搜索的外表,DP的内心。 。 。 

#include <iostream>#include <algorithm>#include <cstdlib>#include <cstdio>#include <cstring>#include <queue>#include <cmath>#include <stack>#pragma comment(linker, "/STACK:1024000000");#define LL long long int#define ULL unsigned long long int#define _LL __int64#define INF 0x3f3f3f3fusing namespace std;_LL dp[35][501];int pre[41];_LL dfs(int n,int m){    if(dp[n][m] != -1)        return dp[n][m];    if(n > m || n == 0 || m == 0)        dp[n][m] = 0;    else if(n == m || n == 1)        dp[n][m] = 1;    else    {        dp[n][m] = 0;        for(int i = n; i >= 1 ;--i)        {            dp[n][m] += dfs(i,m-n);        }    }    return dp[n][m];}int main(){    _LL ans = 0;    int n,i,j;    scanf("%d",&n);    for(i = 2,pre[1] = 1;i <= 40; ++i)    {        pre[i] = pre[i-1] + i;    }    memset(dp,-1,sizeof(dp));    for(i = 1;n >= pre[i]; ++i)        ;    for(--i;i >= 2; --i)    {        for(j = i;j >= 1; --j)            ans += dfs(j,n-pre[i]);    }    printf("%I64d\n",ans);    return 0;}



0 0
原创粉丝点击