bzoj1037[ZJOI2008]生日聚会Party DP
2017-10-02 08:23
399 查看
题意:n个男生m个女生坐成一排,任意一段两者数量之差<=k,求方案数,n,m<=150,k<=20.
这种题都没切我无颜面见江东父老orz。
下意识去找性质,发现好像连续的长度不能超过k?然后想着设f[i][j]表示当前做到第i个位置,最长连续01长度为j的方案数,转移挺好写,问题是前面有的段可能会不符合代价。
比如我k=4,然后000110000就GG了。
事实证明,n,k那么小,吃饱了撑着才去寻找性质,直接暴力DP就好了啊,我丝薄吗。。
设f[i][j][k1][k2],表示当前有n个男生,m个女生,其后缀中男女最大差为k1,女男最大差为k2,转移很显然。
这种题都没切我无颜面见江东父老orz。
下意识去找性质,发现好像连续的长度不能超过k?然后想着设f[i][j]表示当前做到第i个位置,最长连续01长度为j的方案数,转移挺好写,问题是前面有的段可能会不符合代价。
比如我k=4,然后000110000就GG了。
事实证明,n,k那么小,吃饱了撑着才去寻找性质,直接暴力DP就好了啊,我丝薄吗。。
设f[i][j][k1][k2],表示当前有n个男生,m个女生,其后缀中男女最大差为k1,女男最大差为k2,转移很显然。
#include<cstdio> #include<algorithm> #include<cstring> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int N=155; const int mo=1234567; int n,m,k; int f [25][25]; int main() { scanf("%d%d%d",&n,&m,&k); f[0][0][0][0]=1; fo(i,0,n) { fo(j,0,m) { fo(k1,0,min(k,i)) fo(k2,0,min(k,j)) { if (i<n&&k1<k) { f[i+1][j][k1+1][max(0,k2-1)]+=f[i][j][k1][k2]; f[i+1][j][k1+1][max(0,k2-1)]%=mo; } if (j<m&&k2<k) { f[i][j+1][max(0,k1-1)][k2+1]+=f[i][j][k1][k2]; f[i][j+1][max(0,k1-1)][k2+1]%=mo; } } } } int ans=0; fo(i,0,k) fo(j,0,k) { ans=(ans+f [m][i][j])%mo; } printf("%d\n",ans%mo); }
相关文章推荐
- BZOJ 1037 [ZJOI2008]生日聚会Party(单调DP)
- BZOJ 1037: [ZJOI2008]生日聚会Party(区间dp)
- [BZOJ1037][ZJOI2008]生日聚会Party dp
- bzoj 1037: [ZJOI2008]生日聚会Party dp
- bzoj1037: [ZJOI2008]生日聚会Party(dp)
- BZOJ 1037: [ZJOI2008]生日聚会Party [序列DP]
- bzoj1037: [ZJOI2008]生日聚会Party DP
- 【BZOJ1037】[ZJOI2008]生日聚会Party【计数DP】【特殊的姿势】
- bzoj 1037: [ZJOI2008]生日聚会Party (DP)
- [BZOJ 1037][ZJOI2008]生日聚会Party(DP)
- BZOJ 1037: [ZJOI2008]生日聚会Party DP
- bzoj1037:[ZJOI2008]生日聚会Party[DP]
- bzoj 1037: [ZJOI2008]生日聚会Party (dp)
- 【bzoj1037】【ZJOI2008】【生日聚会Party】【dp】
- bzoj 1037 [ZJOI2008]生日聚会Party(DP)
- [BZOJ1037][ZJOI2008][DP]生日聚会Party
- bzoj1037 [ZJOI2008]生日聚会Party(dp)
- [bzoj1037][ZJOI2008]生日聚会Party dp
- BZOJ 1037: [ZJOI2008]生日聚会Party DP
- BZOJ.1037.[ZJOI2008]生日聚会Party(DP)