洛谷 1002 过河卒
虽然这道题目的标签上有高精,但是用long long int就能AC
看到普及-的难度,本蒟蒻二话不说写了DFS,结果...只拿了40分,只好改变思路写了递推(个人认为DP!=递推)。
(DFS代码未AC,无注释)
#include<bits/stdc++.h> using namespace std; int mx,my,ex,ey; bool v[25][25]; long long ans=0; void dfs(int x,int y) { if(x==ex&&y==ey) ans++; if(x>ex || y>ey) return; if(v[x+1][y]==0 && x+1<=ex) dfs(x+1,y); if(v[x][y+1]==0 && y+1<=ey) dfs(x,y+1); return; } int main() { memset(v,0,sizeof(0)); scanf("%d%d%d%d",&ex,&ey,&mx,&my); v[mx][my]=1; v[mx-1][my-2]=1;v[mx+2][my+1]=1;v[mx+1][my+2]=1;v[mx-2][my+1]=1; v[mx-1][my+2]=1;v[mx+2][my-1]=1;v[mx+1][my-2]=1;v[mx-2][my-1]=1; dfs(0,0); printf("%lld",ans); return 0; }
下为AC代码(递推)
由于卒只能向下向右移动,不难得出递推式 f [ i ] [ j ] = f [ i - 1 ] [ j ] + f [ i ] [ j - 1 ] (f [ i ] [ j ]为 起点到点(i,j)的路径数),马的控制区设为0,直接跳过即可。
这里为了防止数组下标为负数,将整个棋盘向右下移动(起点由(0,0)变为(1,1))。
#include<bits/stdc++.h> //万能库 using namespace std; long long f[25][25]; //f[i][j]为 起点到点(i,j)的路径数 int n,m,hx,hy; bool v[25][25]; //v数组记录点(i,j)是否为马的控制区 int main() { scanf("%d%d%d%d",&n,&m,&hx,&hy); n+=1,m+=1,hx+=1,hy+=1; //整体移动,防止负数 f[0][1]=1; //当循环到点(1,1)时,f[1][1]会被计算为1 v[hx][hy]=1; //标记马的控制区 v[hx-1][hy-2]=1;v[hx+2][hy+1]=1;v[hx+1][hy+2]=1;v[hx-2][hy+1]=1; v[hx-1][hy+2]=1;v[hx+2][hy-1]=1;v[hx+1][hy-2]=1;v[hx-2][hy-1]=1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(v[i][j]==1) f[i][j]=0; //跳过马的控制区 else f[i][j]=f[i-1][j]+f[i][j-1]; //递推 printf("%lld",f[n][m]); //(n,m)即为答案 return 0; }