1801: [Ahoi2009]chess 中国象棋
2015-12-15 11:52
369 查看
终于找到一道能做的出来的DP水题了TAT。
仔细想一下会发现其实每一行最多放俩炮,每一列也最多放俩炮。
而且,列和列之间应该是等价的。
so
用f[i][j][k]表示前i行有j列放了0个炮,有k列放了1个炮,自然有m-j-k列放了两个炮。
然后压掉第1维。
每一行的状态转移有三种:不放,放一个,放两个。
随便搞搞就出来了。
仔细想一下会发现其实每一行最多放俩炮,每一列也最多放俩炮。
而且,列和列之间应该是等价的。
so
用f[i][j][k]表示前i行有j列放了0个炮,有k列放了1个炮,自然有m-j-k列放了两个炮。
然后压掉第1维。
每一行的状态转移有三种:不放,放一个,放两个。
随便搞搞就出来了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int mod=9999973; long long f[2][105][105]; int main(){ int n,m;scanf("%d%d",&n,&m); if(n<m)swap(n,m); f[0][m][0]=1; for(int i=1;i<=n;i++){ int now=i&1,last=!now; memset(f[now],0,sizeof(f[now])); for(int j=0;j<=m;j++)//有j列是0个炮 for(int k=0;k+j<=m;k++)//有k列是1个炮 { int h=m-j-k; //有h列是2个炮 不能再多了,再多要炸 if(!f[last][j][k])continue; f[now][j][k]+=f[last][j][k]; //不放 f[now][j][k]%=mod; if(j>0){ //放一个 f[now][j-1][k+1]+=f[last][j][k]*j; f[now][j-1][k+1]%=mod; } if(k>0){ f[now][j][k-1]+=f[last][j][k]*k; f[now][j][k-1]%=mod; } if(j>1){ f[now][j-2][k+2]+=f[last][j][k]*j*(j-1)/2; f[now][j-2][k+2]%=mod; } if(k>1){ f[now][j][k-2]+=f[last][j][k]*k*(k-1)/2; f[now][j][k-1]%=mod; } if(j>0&&k>0){ f[now][j-1][k]+=f[last][j][k]*j*k; f[now][j-1][k]%=mod; } } } long long ans=0; for(int i=0;i<=m;i++) for(int j=0;i+j<=m;j++){ ans+=f[n&1][i][j]; ans%=mod; } printf("%lld",ans); return 0; }
相关文章推荐
- zigbee网关 cc2530终端裸机串行驱动12864(字库ST7920)显示图片
- LeetCode--Best Time to Buy and Sell Stock (贪心策略 or 动态规划)
- zookeeper原理
- AFNetWorking源码学习摘要
- Linux系统复制vmware 虚拟机后网卡不能启动该怎么办?
- JDBC监听器-P6Spy
- Kinect for Windows SDK开发入门(十九):Kinect Fusion
- iOS开发UI篇—ios应用数据存储方式(归档)
- window下的网络命令
- C# MySQL Helper
- python+Tornado + Supervisor + nginx部署
- AOE求关键路径
- 注册表实现右键自定义多级菜单
- hdu 4107当卡段树
- android xmlns:tools用法
- /dev/sda3: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY
- iOS-----检测网络状态
- Kinect for Windows SDK 1.8的改进及新特性
- hdu 3466 01背包变种
- 即兴演讲法