洛谷P1002
一道入门dp题
第一次看到这种题,可能第一时间想到的就是搜索,发现只能过几个点,然后想到既然题中提到了求路径条数,且数据将会很大,所以自然应想到dp才是正解。
dp策略:
1.记当卒走到地图上(i,j)点时,路径条数为f[i][j]
2.因为卒只能往下或者往右走,不难得出转移方程:
f[i][j] = max(f[i][j],f[i-1][j] + f[i][j-1])
3.用两次for循环遍历途中每个点,更新f[i][j]
4.当然此转移方程并不是最优的,还可以进行滚动数组压缩,压缩后的转移方程:
f[i] = f[i] + f[i-1]
注意事项:
1.此题数据很大,要用unsigned long long
存储
2.用dx和dy两个数组标记地图上马的拦路点,这个应该有点图论基础的都知道
3.每个坐标+2,防止越界
话不多说,干代码:
//dp题
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cctype>
#include <string>
#include <sstream>
#include <stack>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#define LL long long
#define ULL unsigned long long
#define INF 1000000001
using namespace std;
const int maxn = 22;
const int fx[] = { 0, -2, -1, 1, 2, 2, 1, -1, -2 };
const int fy[] = { 0, 1, 2, 2, 1, -1, -2, -2, -1 };
int x, y, mx, my;
ULL f[30][30];//f[i][j]代表从A点到(i,j)会经过的线路数
bool s[30][30];//判断这个点有没有马盯着
int main() {
scanf("%d%d%d%d", &x, &y, &mx, &my);
x += 2; y += 2; mx += 2; my += 2;
//坐标+1以防越界
f[2][2] = 1;//初始化
s[mx][my] = 1;//标记马的位置
for (int i = 1; i <= 8; i++)
s[mx + fx[i]][my + fy[i]] = 1;
for (int i = 2; i <= x; i++) {
for (int j = 2; j <= y; j++) {
if (s[i][j])continue;
f[i][j] = max(f[i][j], f[i - 1][j] + f[i][j - 1]);
//状态转移方程
}
}
printf("%llu\n", f[x][y]);
return 0;
}
感兴趣的小伙伴可以自己动手打一下一维数组版的代码,也不是很难