计数DP-NEFU1208-好好思考

http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=1208
n天的课程,如果连续超过m个就会发生爆炸,问你不会发生爆炸的情况。
以前写的时候以为这是一个排列问题,后来看了好多已经确定这是一个DP了。
开始想用递推写,没有递推好,
思路:dp[i][j],i为截止到当前的天数,考试天数达到j的次数。
这样就可以发现两个递推方程。
1 第i天天数达到0的天数等于所有 dp[i-1][j]的累加。(第i天没有考试)
2 第i天天数达到j的天数等于 所有dp[i-j][0]的情况,(i-j到i的情况都是固定的,一定考试。但i-j这一天不考试,第i天考试)。
至少为1天。(如果是0天的话,在第一个已经包括了)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
/*这是一个计数的dp,这种东西如果没有思路的话很容易想成
其他算法,比方说排列组合之类的。
其实是一个计数的dp
分为两种,当当前数为0时候。所有的结果等于之前的相加。
当当前不为0时,等于前面出现j个连续的相加。
(我其实还是不太懂这个东西,)
题目最大是50,所以要用long,long
*/
using namespace std;
long long dp[105][10];
int main(){
    long long n,m,i,j,ans;
    //freopen("boom.in","r",stdin);
    //freopen("boom.out","w",stdout);
      //cout<<(long long )pow(2,50)<<endl;
    while(~scanf("%lld%lld",&n,&m))
        {   memset(dp,0,sizeof(dp));
            dp[0][0]=1;//什么都不存在也是1
            for( i=1;i<=n;i++)
            {  for( j=0;j<m;j++)
                dp[i][0]+=dp[i-1][j];
                for( j=1;j<=min(i,m-1);j++)
                    dp[i][j]+=dp[i-j][0];
            }
         ans=0;
        for( i=0;i<m;i++)
             ans+=dp[n][i];
        cout<<ans<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值