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;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章