1. 程式人生 > 其它 >【洛谷P1002】——過河卒dp問題

【洛谷P1002】——過河卒dp問題

在解動態規劃問題時,許多人認為找到狀態轉移方程是最難的,我也認同這一觀點。一道動態規劃題能找到狀態轉移方程就完成了一半。

然而另一半在我看來有時候比找狀態轉移方程更噁心——dp陣列的初始化以及越界問題。

想要克服以上兩個問題都需要大量的練習。任重而道遠。

題目描述:

#include<iostream>
#include<vector>
using namespace std;


int main() {
	vector<int> dirX{ -1,-2,-2,-1,1,2,2,1 };
	vector<int> dirY{ 2,1,-1,-2,-2,-1,1,2 };

	int bx, by, mx, my;
	cin >> bx >> by >> mx >> my;

	vector<vector<long long>> dp(bx + 1, vector<long long>(by + 1,0));
	vector<vector<bool>> flag(bx + 1, vector<bool>(by + 1, false));
	for (int i = 0; i < 8; i++) 
		if(mx+dirX[i]>=0&&my+dirY[i]>=0&&mx+dirX[i]<bx+1&&my+dirY[i]<by+1)
			flag[mx + dirX[i]][my + dirY[i]] = true;
	flag[mx][my] = true;
	dp[0][0] = 1;

	for(int i=0;i<=bx;i++)
		for (int j = 0; j <= by; j++) {
			if (flag[i][j])
				continue;
			if (i)
				dp[i][j] += dp[i - 1][j];
			if (j)
				dp[i][j] += dp[i][j - 1];
		}
	cout << dp[bx][by];
	return 0;
}

關鍵點:題目中起點的座標是(0,0),我們可以直接將它作為起點,也可以橫縱座標都加上1作為起點。這兩種情況下一定要注意陣列越界問題和狀態轉移方程的程式語言的呈現。題目中的狀態轉移方程為dp[i][j]=dp[i-1][j]+dp[i][j-1].可見如果我們直接將狀態轉移方程直接敲到程式碼中去,當i=0或j=0時會發生越界。因此我們要將這兩種情況區分出來。由題意可知當i=0時,如果flag[i][j]=0,那麼dp[i][j]=dp[i][j-1],同理當j=0,flag[i][j]=0時,dp[i][j]=dp[i-1][j]。當i>0&&j>0時,dp[i][j]=dp[i-1][j]+dp[i][j-1]。因此我們便可將其寫為上述程式碼中第二個for迴圈中的樣子。