题目大意
给定一个矩形网格的长m和高n,其中m和n都是unsigned int32类型,一格代表一个单位,就是一步,求从左下角到右上角有多少种走法,每步只能向上或者向右走
解题思路
首先题目上说了答案不会超过int型变量,我们可以简单算一下,如果是 2 ∗ x 2*x 2∗x的图,大概 x x x在100000左右就会超出int变量的范围,如果是 3 ∗ x , , , m ∗ x 3*x,,,m*x 3∗x,,,m∗x的图,那么 x x x的范围会更小,当 1 ∗ x 1*x 1∗x时,返回 x + 1 x+1 x+1, 0 ∗ x 0*x 0∗x时返回 1 1 1,然后我们讨论 m ∗ n m*n m∗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;
}
}