洛谷 P1002 [NOIP2002 普及组] 过河卒
思路
普普通通的动态规划(DP)模板题。
选择分两块来讨论问题。
首先处理一下马能移动到的位置,只需要在马所在的坐标和其能移动的八个点位标记即可。通过以下代码实现。
const int dir[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}};//移动数组,存下来马每种移动时位置的相对变化
d[cx][cy]=true;//把马本体标记
for(int i=0;i<8;i++){
int tx=cx+dir[i][0],ty=cy+dir[i][1];//移动
if(tx>=0&&tx<=n&&ty>=0&&ty<=m)//如果在边界内
d[tx][ty]=true;//标记
}
然后开始讨论移动的问题,不难发现,点
所以得出状态转移方程
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
if(d[i][j]==false){//如果没被标记
if(i)//判边界
dp[i][j]+=dp[i-1][j];//转移
if(j)//判边界
dp[i][j]+=dp[i][j-1];//转移
}
}
}
AC Code
#include<bits/stdc++.h>
using namespace std;
const int dir[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}};
bool d[30][30];
long long dp[30][30],n,m,cx,cy;
int main(){
cin>>n>>m>>cx>>cy;
d[cx][cy]=true;
for(int i=0;i<8;i++){
int tx=cx+dir[i][0],ty=cy+dir[i][1];
if(tx>=0&&tx<=n&&ty>=0&&ty<=m) d[tx][ty]=true;
}
dp[0][0]=1;
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
if(d[i][j]==false){
if(i) dp[i][j]+=dp[i-1][j];
if(j) dp[i][j]+=dp[i][j-1];
}
}
}
cout<<dp[n][m]<<endl;
return 0;
}