POJ 1942 Paths on a Grid【題解報告|DP巧妙的解決組合數問題】

題目大意

給定一個矩形網格的長m和高n,其中m和n都是unsigned int32類型,一格代表一個單位,就是一步,求從左下角到右上角有多少種走法,每步只能向上或者向右走

解題思路

首先題目上說了答案不會超過int型變量,我們可以簡單算一下,如果是2x2*x的圖,大概xx在100000左右就會超出int變量的範圍,如果是3x,,,mx3*x,,,m*x的圖,那麼xx的範圍會更小,當1x1*x時,返回x+1x+10x0*x時返回11,然後我們討論mnm*n的場景

首先,拿出我們的dp公式,

		for (int i = 1; i <= n; i++)dp[i][1] = 1;
		for (int i = 1; i <= m; i++)dp[1][i] = 1;

		for (int i = 2; i <= n; i++)
			for (int j = 2; j <= m; j++)
				dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

此時一個維度最小開100000,那麼很容易MLE,可以觀察到這裏可以使用滾動數組進行一步優化,直接就避免了MLE的情況

		for (int i = 2; i <= n; i++)
			for (int j = 2; j <= m; j++)
				dp[i % 2][j] = dp[(i % 2) ^ 1][j] + dp[i % 2][j - 1];

很多人會遇到TLE的問題,這是因爲一個維度=1時,另一個維度可以非常大,因此我們講一維=1的情況單獨進行討論就避免了TLE。

完整代碼

//1724K	32MS
#define inf 0x3f3f3f3f
#define ll long long
#define vec vector<int>
#define P pair<int,int>
#define MAX 100000

ll n, m, dp[2][MAX];
string s, t;

int main() {
	while (scanf("%lld %lld", &m, &n) && n + m) {
		memset(dp, 0, sizeof(dp));

		if (m > n)swap(n, m);
		if (m == 0) { cout << 1 << endl; continue; }
		if (m == 1) { cout << n + 1 << endl; continue; }
		n++, m++;
		for (int i = 1; i <= m; i++)dp[1][i] = 1;
		dp[0][1] = dp[1][0] = 1;

		for (int i = 2; i <= n; i++)
			for (int j = 2; j <= m; j++)
				dp[i % 2][j] = dp[(i % 2) ^ 1][j] + dp[i % 2][j - 1];

		cout << dp[n % 2][m] << endl;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章