棋盘村
Time Limit: 1000 MS Memory Limit: 32768 K
Description
一名骑着马的强盗闯进了原本平静祥和的棋盘村,为了通知村里的士兵来打败强盗,你必须要通知位于棋盘村最下方的兵营。棋盘村的地形就像是一张棋盘,你所在的位置为A点(0,0),兵营位于棋盘村的右下角B点(n,m)。你每次只能走一步,可以选择向下走,也可以选择向右走。但是强盗所在的位置和强盗的马一次所能跳到的位置是不可以走过去的(强盗的马的移动方法与象棋中的马相同)。请计算出从A点能够走到B点的所有路径条数。
Input
首先输入一个整数t,代表有t组测试数据。
每组测试数据为四个整数,即B点的坐标(n,m)和强盗的坐标(x,y)。
1 < n,m < 20.
Output
输出一个整数即路径的条数。
Sample Input
2
6 6 3 2
8 8 3 5
Sample Output
17
1393
Source
2016级新生程序设计全国邀请赛
题意
路径统计
思路
简单dp。
每一点的路径数等于dp[i][j] = dp[i-1][j] + dp[i][j-1]
即每一点的可能路径数为从从左边走的路径数目加上从右边走的路径数量。
dp[i][j] = dp[i-1][j] + dp[i][j-1];
若这个点的左边有强盗且上面有强盗那么这个点的路径就为0了。
if(dp[i-1][j]==-1&&dp[i][j-1]==-1){
dp[i][j] = 0;
}
若这个点的左边有强盗那么这个点的路径数就是从上走的路径数。
if(dp[i-1][j]==-1){
dp[i][j] = dp[i][j-1];
上面有强盗同理。
if(dp[i][j-1]==-1){
dp[i][j] = dp[i-1][j];
注意一开始标记强盗点时候的数组越界的判定。
坑点
注意强盗点的标记和数组越界的处理。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX 26
int n,m,x,y;
ll dp[MAX][MAX];
bool judge(int x,int y)
{
if(x>=0&&x<=n&&y>=0&&y<=m) return true;
else return false;
}
void solve(void)
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>x>>y;
memset(dp,0,sizeof dp);
if(judge(x,y)) dp[x][y] = -1;
if(judge(x-1,y-2)) dp[x-1][y-2] = -1;
if(judge(x-2,y-1)) dp[x-2][y-1] = -1;
if(judge(x-2,y+1)) dp[x-2][y+1] = -1;
if(judge(x-1,y+2)) dp[x-1][y+2] = -1;
if(judge(x+1,y-2)) dp[x+1][y-2] = -1;
if(judge(x+2,y-1)) dp[x+2][y-1] = -1;
if(judge(x+2,y+1)) dp[x+2][y+1] = -1;
if(judge(x+1,y+2)) dp[x+1][y+2] = -1;
dp[0][0] = 1;
dp[n][m] = 0;
int flag = 0;
///初始化一下边界值。最上面一行的路径肯定为1.如果有强盗那么强盗之后的路径就走不到了。
for(int i = 0 ; i <= m ; i++){
if(dp[0][i]!=-1&&flag==0){
dp[0][i] = 1;
}
if(dp[0][i]==-1) flag = 1;
}
flag = 0;
///最左边的一行同理。
for(int i = 1 ; i <= n ; i++){
if(dp[i][0]!=-1&&flag==0){
dp[i][0] = 1;
}
if(dp[i][0]==-1) flag = 1;
}
for(int i = 1 ; i <= n ;i++){
for(int j = 1 ; j <= m ; j++){
if(dp[i][j]!=-1){
if(dp[i-1][j]==-1&&dp[i][j-1]==-1){
dp[i][j] = 0;///左边,上面全是强盗。
}
else if(dp[i-1][j]==-1){
dp[i][j] = dp[i][j-1];///左边是强盗。
}
else if(dp[i][j-1]==-1){
dp[i][j] = dp[i-1][j];///上面是强盗。
}
else dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
}
// for(int i = 1 ; i <= n ; i++){
// for(int j = 1 ; j <= m ; j++)
// {
// printf("%4I64d ",dp[i][j]);
// }
// cout<<endl;
// }
cout<<dp[n][m]<<endl;
}
}
int main(void)
{
solve();
return 0;
}