这是一道非常好的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