动态规划的引入1

动态规划的引入

之前学习过一段时间的动态规划,但掌握的不够牢固,实际做题时还是不能灵活的运用,所以打算在寒假对这部分知识进行学习和巩固,按照洛谷的提单分为五个部分进行学习:
1.动态规划的引入
2.线性状态动态规划
3.区间与环形动态规划
4.树与图上的动态规划
5.状态压缩动态规划
本文题目选自第一部分的练习内容

题目:过河卒
题目内容:棋盘上 AA 点有一个过河卒,需要走到目标 BB 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 CC 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。棋盘用坐标表示,AA 点 (0, 0)(0,0)、BB 点 (n, m)(n,m),同样马的位置坐标是需要给出的。现在要求你计算出卒从 AA 点能够到达 BB 点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步。
样例: 输入:6 6 3 3 输出: 6

解题过程:这道题很明显要用动态规划的思想来做,直接算出有多少条路是不现实的,所以拆分成算每一格有多少条路,并把马的控制点做为动态规划的条件:
1.当上一步和左一步都是马的控制点时,到这一步的路数为: 0+0 = 0
2.当仅有上一步是马的控制点时,到这一步的路数为: 0 + 左一步的路数 = 左一步的路数
3.当仅有左一步是马的控制点时,到这一步的路数为: 上一步的路数 + 0 = 上一步的路数
3.当上一步和左一步都不是马的控制点时,到这一步的路数为: 上一步的路数+左一步的路数
代码为:

if(area[i-1][j]==-1 && area[i][j-1]==-1) area[i][j] = 0;
	else if(area[i-1][j]==-1) area[i][j] = area[i][j-1];
		else if(area[i][j-1]==-1) area[i][j] = area[i-1][j];
			else area[i][j] = area[i][j-1] + area[i-1][j];

注意判断边界,即马的控制点会不会超出棋盘范围:

if(hx-2 >= 0 && hy-1 >=0)
		area[hx-2][hy-1] = -1;
if(hx-1 >= 0 && hy-2 >=0)
		area[hx-1][hy-2] = -1;
if(hx+1 <= bx && hy-2 <= by)
		area[hx+1][hy-2] = -1;
if(hx+2 <= bx && hy-1 >=0)
		area[hx+2][hy-1] = -1;

最后还要注意路数会超出int范围,所以dp数组要用long long int存储(因为这个细节第一次提交WA的两个样例):

long long int area[25][25];

全部代码

#include
using namespace std;

long long int area[25][25];
int bx,by,hx,hy;
void init(){
     
	for(int i=0;i<=by;i++){
     
		if(area[0][i] != -1) area[0][i] = 1;
		else break;
	}
	for(int j=0;j<=bx;j++){
     
		if(area[j][0] != -1) area[j][0] = 1;
		else break;
	}
}
void dp(){
     
	for(int i=1;i<= bx;i++){
     
		for(int j=1;j<=by;j++){
     
			if(area[i][j] == -1) continue;
			if(area[i-1][j]==-1 && area[i][j-1]==-1) area[i][j] = 0;
			else if(area[i-1][j]==-1) area[i][j] = area[i][j-1];
			else if(area[i][j-1]==-1) area[i][j] = area[i-1][j];
			else area[i][j] = area[i][j-1] + area[i-1][j];
		} 
	}
}
int main(){
     
	cin >> bx >> by >> hx >> hy;
	area[hx][hy] = -1;
	if(hx-2 >= 0 && hy-1 >=0)
		area[hx-2][hy-1] = -1;
	if(hx-1 >= 0 && hy-2 >=0)
	area[hx-1][hy-2] = -1;
	if(hx+1 <= bx && hy-2 <= by)
	area[hx+1][hy-2] = -1;
	if(hx+2 <= bx && hy-1 >=0)
	area[hx+2][hy-1] = -1;
	if(hx-2 >= 0 && hy+1 <= by)
	area[hx-2][hy+1] = -1;
	if(hx-1 >= 0 && hy+2 <= by)
	area[hx-1][hy+2] = -1;
	if(hx+1 <= bx && hy+2 <= by)
	area[hx+1][hy+2] = -1;
	if(hx+2 <= bx && hy+1 <= by)
	area[hx+2][hy+1] = -1;
	init();
	dp();
	cout << area[bx][by];
} 

心得
通过今天的练习,我复习了之前练习的动态规划的题目,学习了动态规划的思想,即把一个无法直接得到答案的复杂问题分成若干个较简单的小问题,通过对小问题进行求解并汇总最终得到大问题的答案,这一思想不仅在编程中很厉害,在现实生活中对我也有所启发。

你可能感兴趣的:(寒假算法练习,动态规划,算法,编程语言,algorithm,acm竞赛)