bzoj 1037 [ZJOI2008]生日聚会Party

5 篇文章 0 订阅

这是一道非常好的dp题,实在是太好了

机房众神犇都说这是一道水题

然而我却做了一上午,这可让我这种菜鸡怎么办啊 qwq

这个题一看就是dp,但是我第一眼看像是区间dp???

这个题要男生与女生的差不超过 k (常数)怎么维护???

然后得到神犇的指点说其实可以只维护以 i 为结尾的所有后缀的情况就好啦

f[i][j][a][b] 表示 以 i 为结尾的所有后缀中 男生有 j个,男-女最大为a,女-男最大为b的情况数

首先他可以表示所有的情况

其次它不会有不合法的情况也就是我一直纠结的地方

看起来中间好像可能会不合法没有被考虑到,但是其实这种情况是dp不过来的啦

还有一个问题,那就是 0->负数统统变成 0 这个真的对吗?

以后递推的时候 0->1 的时候难道不是把负数也变成1了吗?

我要说 错是错了,但也是对的。

玄学

因为最后求得是和,对于和来说 这些状态都是合法的,所以加起来是全面的,正确的。

但是你直接输出一个dp值,肯定和它原来的含义不符合了

感性理解

然后就可以愉快的dp啦

#include<bits/stdc++.h>
using namespace std;
const int P=12345678;
int n,m,k;
int f[305][155][22][22];
int main()
{
//  freopen("a.in","r",stdin);
//  freopen("a.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    f[0][0][0][0]=1;
    for(int i=0;i<=n+m;i++)
    {
       for(int j=0;j<=min(i,n);j++)
       {
          for(int a=0;a<=min(k,i);a++)
          {
             for(int b=0;b<=min(k,i);b++)
             {
                if(a<k) 
                {
                   f[i+1][j+1][a+1][max(0,b-1)]=(f[i+1][j+1][a+1][max(0,b-1)]+f[i][j][a][b])%P;
                }
                if(b<k)
                {
                   f[i+1][j][max(0,a-1)][b+1]=(f[i+1][j][max(0,a-1)][b+1]+f[i][j][a][b])%P;    
                }
             }
          }
       }
    }
    long long ans=0;
    for(int i=0;i<=k;i++) for(int j=0;j<=k;j++) 
     ans=(ans+f[n+m][n][i][j])%P;
    printf("%lld\n",ans);
}

心得:
1.dp我很菜,要好好刷题!!!!!
2.dp要点:可以遍历所有情况,不包含不合法状态或者是不合法推不过来!!!!
3.批处理新招数:

美滋滋啊

@echo off
:again
mkd.exe
未命名2.exe
未命名1.exe
fc a.out aa.out > nul   
if not errorlevel 1 goto again
pause
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值