首页 > 代码库 > 炮(棋盘DP)
炮(棋盘DP)
一直以为自己写的就是状态压缩,结果写完才知道是个棋盘dp
首先看一下题目
嗯,象棋 ,还是只有炮的象棋
对于方案数有几种,我第一个考虑是dfs,但是超时稳稳的,所以果断放弃
然后记得以前有过和这个题差不多的dp题
所以思路开始转向DP
经仔细思考后 将棋盘的状态压为三维
dp[i][k][j];
i:棋盘的第几行 k:前i行有几列放了一个炮棋 j:前i行有几列放了两个炮棋
因为炮会隔棋打,所以一列或者一行最多存在两个炮棋
所以
dp方程有6个元素:
1:不放炮棋,所以方程为 dp[i][k][j]+=dp[i-1][k][j];
2:往一个没有炮棋的列放一个炮棋,方程为dp[i][j][k]+=dp[i-1][k-1][j]*(m-k-j+1);
3:往一个有一个炮棋的列放一个炮棋,方程为dp[i][j][k]+=dp[i-1][k+1][j-1]*(k+1);
4:往一个有一个炮棋的列放一个炮棋同时往一个没有炮棋的列放一个炮棋,方程为dp[i][j][k]+=dp[i-1][k][j-1]*(k)*(m-j-k+1)/2;
5:往一个有一个炮棋的列放一个炮棋同时往一个有一个炮棋的列放一个炮棋,方程为dp[i][k][j]+=(k+2)*(k+1)/2*dp[i-1][k+2][j-2];
6:往一个没有炮棋的列放一个炮棋同时往一个没有炮棋的列放一个炮棋,方程为dp[i][k][j]+=(m-j-k+2)*(m-j-k+1)/2*dp[i-1][k-2][j];
好了,现在可以贴代码了
#include<cstdio> #include<iostream> #define mod 999983 using namespace std; int n,m; long long int dp[101][101][101],ans=0; int main() { scanf("%d%d",&n,&m); dp[0][0][0]=1; for(int i=1;i<=n;i++) { for(int k=0;k<=m;k++) { for(int j=0;j<=m-k;j++) { dp[i][k][j]=dp[i-1][k][j]; if(k) dp[i][k][j]+=(m-k-j+1)*dp[i-1][k-1][j]%mod; if(j&&k<m) dp[i][k][j]+=(k+1)*dp[i-1][k+1][j-1]%mod; if(k>1) dp[i][k][j]+=(m-j-k+2)*(m-j-k+1)/2*dp[i-1][k-2][j]%mod; if(j>1&&k<m-1) dp[i][k][j]+=(k+2)*(k+1)/2*dp[i-1][k+2][j-2]%mod; if(k&&j) dp[i][k][j]+=(m-j-k+1)*(k)*dp[i-1][k][j-1]%mod; dp[i][k][j]%=mod; } } } for(int i=0;i<=m;i++) { for(int j=0;j<=m-i;j++) { ans+=dp[n][i][j]; ans%=mod; } } printf("%lld\n",ans); return 0; }
炮(棋盘DP)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。