原题链接:信息学奥赛一本通T1314-过河卒
解题思路:
首先考虑暴力解法,果不其然会超时,然后发现每个点的状态只会由左边一个点和上边一个点转化而来,想到用dp,令dp[x][y]为到该点的路径数量,可知
dp[x][y]=dp[x-1][y]+dp[x][y-1]。
注意事项:
//需要注意初始化第一行(列)时,第一行(列)没有非法点时,第一行(列)全为1
//但当第一行(列)有非法点时,无法达到非法点后续位置,故非法点及之后的点会全为0
前半部分为DFS做法,会超时,可以直接参考后半部分的dp做法。
参考代码:
#include <iostream>
#include <vector>
using namespace std;
/*暴力DFS做法
vector<int> unlow_x, unlow_y;
int res = 0;
int a, b, c, d;
bool find(int x, int y) {
for (int i = 0; i < unlow_x.size(); i++) {
if (x == unlow_x[i] && y == unlow_y[i])
return true;
}
return false;
}
void dfs(int x, int y) {
if (x == a && y == b) {
res++;
return;
}
if (find(x,y)||x>a||y>b)
return;
dfs(x + 1, y);
dfs(x, y + 1);
}
int main()
{
cin >> a >> b >> c >> d;
unlow_x.push_back(c + 1);
unlow_y.push_back(d + 2);
unlow_x.push_back(c + 1);
unlow_y.push_back(d - 2);
unlow_x.push_back(c - 1);
unlow_y.push_back(d + 2);
unlow_x.push_back(c - 1);
unlow_y.push_back(d - 2);
unlow_x.push_back(c + 2);
unlow_y.push_back(d + 1);
unlow_x.push_back(c + 2);
unlow_y.push_back(d - 1);
unlow_x.push_back(c - 2);
unlow_y.push_back(d + 1);
unlow_x.push_back(c - 2);
unlow_y.push_back(d - 1);
unlow_x.push_back(c);
unlow_y.push_back(d);
dfs(0, 0);
cout << res;
return 0;
}*/
/*DP做法*/
//(a,b)为终点坐标,(c,d)为马坐标,fx,fy存储非法点相对马的dx和dy
int a, b, c, d;
vector<int> fx{ 0,1,1,2,2,-1,-1,-2,-2 }, fy{ 0,2,-2,1,-1,2,-2,1,-1 };
/*判断是否为合法点,如果该点是非法点,返回false*/
bool judge(int x, int y) {
for (int i = 0; i < fx.size(); i++) {
if (x == c + fx[i] && y == d + fy[i])
return false;
}
return true;
}
int main() {
cin >> a >> b >> c >> d;
//初始化dp表,dp[x][y]表示到(x,y)点的路径数量
//需要注意当第一行(列)没有非法点时,第一行(列)全为1
//但当其有非法点时,无法达到非法点后续位置,故非法点及之后的点会全为0
vector<vector<long long>> dp(a + 1, vector<long long>(b + 1, 0));
//初始化第一行
for (int i = 0; i <= b; i++) {
if (judge(0, i))
dp[0][i] = 1;
else break;
}
//初始化第一列
for (int j = 0; j <= a; j++) {
if (judge(j, 0))
dp[j][0] = 1;
else break;
}
//开始动态规划,dp[x][y]=dp[x-1][y]+dp[x][y-1]
for (int i = 1; i <= a; i++) {
for (int j = 1; j <= b; j++) {
if (judge(i, j)) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
}
cout << dp[a][b];
return 0;
}0.0分
0 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复