2020第十一届蓝桥杯7月省赛E题

2020第十一届蓝桥杯7月省赛E题

试题E:矩阵

题目描述:
1

本题思路:
这道题如果暴力跑,2020层递归调用(爆栈先不说,我们学校的电脑绝对要先死机)
这道题我用dp写的(嘿嘿,在这里感谢一下yzzz)。
首先,我们初读题目可以发现:第一排的最左边一定是1,第二排的最右边一定是2020。因为要求右边比左边大,下面比上面大,那么我们可以得知第一排一定是升序排列,第二排也一定是升序排列,那么我们只要顺序遍历其实就是可以满足升序的要求的,现在需要解决的就是同一列上下面的数大于上面的数的要求。
因为2020这个数字比较大,我们不妨先模拟一下较小的数字。我们模拟n = 6的场景:一共有五种方案
case1:

123
456

case2:

124
356

case3:

134
256

case4:

135
246

case5:

125
346

我们模拟上面的式子过程中,很容易发现以下特性:
在顺序模拟过程中,我们可以无条件的在第一行填写数字;
第二行填写数字的要求是:只有当同一列的第一行有数字时我们才可以进行填写。(这样子可以满足同一列中第二行的数字比第一行的数字大的要求,原因是我们是顺序遍历的,后面的数字肯定比前面的数字大)
所以我们用dp[i][j]表示第一排放i个数,第二排放j个数时的方案数。
状态转移方程:dp[i][j]的状态从dp[i-1][j]和dp[i][j-1]的状态得到,即上面放i个数,下面放j个数的状态从上面放i-1个数,下面放j个数的状态 和 上面放i个数,下面放j - 1个数的状态得到。
根据上面所说:
第一行的数字是无条件放置的,我们直接可以将dp[i-1][j]的状态转移到dp[i][j]上去,将第i个数放在第一行,即dp[i][j] += dp[i - 1][j]。
只有当j - 1 < i时,即上一个状态上第一行放的个数大于第二行放的个数,我们才可以进行第二行的放置,将第j个数放在第二行,即dp[i][j] += dp[i][j - 1]。

初始化部分:
根据第一行无条件放置的特性,我们可以进行相应的操作,将dp[i][0] = 1;代表第一行放置i个数,第二行放置0个数的方案数为1,因为第二行没有数字,所以第一行只能顺序走下去嘛。

在循环内部记得模2020哟。
所以我们最后输出的就是dp[1010][1010];
答案就是:1340

代码部分:

#include <bits/stdc++.h>
using namespace std;
const int N = 2025;

int dp[N][N];

int main()
{
	int n = 2020;
	for (int i = 1; i < 1011; i++)
	{
		dp[i][0] = 1;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			dp[i][j] += dp[i][j - 1];
			if (i - 1 >= j)
			{
				dp[i][j] += dp[i - 1][j];
			}
			dp[i][j] %= 2020;
		}
	}
	cout << dp[1010][1010] << endl;
	return 0;
} 
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃酱斯密酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值