洛谷P1002 过河卒

洛谷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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#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;
}

感兴趣的小伙伴可以自己动手打一下一维数组版的代码,也不是很难

你可能感兴趣的:(dp)