洛谷 P1736 创意吃鱼法

本文深入探讨了寻找矩阵中最大正方形的算法实现,通过动态规划的方法,利用两个辅助矩阵来记录非零元素的最长连续长度,从而找到最大的正方形。文章详细介绍了算法流程,并附带了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

和最大正方形很像。
记得对角线有两条
还有2500不要开成3000,否则会mle

#include<cstdio>
#include<algorithm>
#include<cstring>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std;

const int MAXN = 2512;
int f[MAXN][MAXN], x[MAXN][MAXN], y[MAXN][MAXN];
int a[MAXN][MAXN], n, m, ans, now;

int main()
{
	scanf("%d%d", &n, &m);
	_for(i, 1, n)
		_for(j, 1, m)
			scanf("%d", &a[i][j]);
	 
	_for(i, 1, n)
		_for(j, 1, m)	
		{
			if(a[i][j])
			{	
				f[i][j] = min(f[i-1][j-1], min(y[i][j-1], x[i-1][j])) + 1;
				ans = max(ans, f[i][j]);
			}
			else 
			{
				x[i][j] = x[i-1][j] + 1;
				y[i][j] = y[i][j-1] + 1;
			}
	}
	
	memset(f, 0, sizeof(f));
	memset(x, 0, sizeof(x));
	memset(y, 0, sizeof(y));
	
	_for(i, 1, n)
		for(int j = m; j >= 1; j--)	
		{
			if(a[i][j])
			{	
				f[i][j] = min(f[i-1][j+1], min(y[i][j+1], x[i-1][j])) + 1;
				ans = max(ans, f[i][j]);
			}
			else 
			{
				x[i][j] = x[i-1][j] + 1;
				y[i][j] = y[i][j+1] + 1;
			}
	}

	printf("%d\n", ans);
	
	return 0;
}

 

### 洛谷 P3925 小猫分鱼 的算法分析 #### 问题描述 给定两个正整数 $N$ 和 $i$,表示有 $N$ 只小猫要分一堆鱼。初始时有一堆数量未知的鱼,记作 $X$。按照如下规则分配: 1. 如果当前剩余鱼的数量可以被 $(N-1)$ 整除,则将其中的一份(即 $\frac{X}{(N-1)}$)丢弃; 2. 剩下的部分平均分给剩下的 $N$ 只小猫。 最终目标是找到最小的可能的初始鱼的数量 $X$,使得经过若干次操作后能够完成上述过程[^1]。 --- #### 解题思路 该问题的核心在于模拟整个分配流程并验证是否存在符合条件的初始值 $X$。以下是具体的解决方法: 1. **变量定义** - 设初始鱼的数量为 $X$。 - 对于任意时刻,设当前鱼的数量为 `ans`,则其计算方式为: \[ ans = j \cdot N + i \] 其中 $j$ 是一个试探性的系数,用于寻找满足条件的最小值。 2. **循环判断合法性** - 使用外层循环不断增大 $j$ 的值,直到找到第一个满足条件的情况为止。 - 内部通过嵌套循环逐步检验每一轮的操作是否合法。具体来说,在第 $k$ 轮 ($1 \leq k < N$),需要检查当前鱼的数量能否被 $(N-1)$ 整除。如果不成立,则退出本轮尝试;否则继续下一轮。 3. **终止条件** - 当某轮迭代完成后未触发任何非法状态(即全程都能成功执行),即可认为找到了合适的解,并输出对应的 `ans` 值。 4. **复杂度分析** 外层循环次数取决于输入规模以及数据特性,但由于每次都会增加固定步长,因此总体效率较高。内部逻辑主要涉及简单的模运算与乘法操作,时间开销较小。 --- #### C++ 实现代码 下面是基于以上策略编写的完整程序: ```cpp #include <bits/stdc++.h> using namespace std; int main() { long long n, i; cin >> n >> i; // 输入参数 N 和 i for (long long j = 1;; ++j) { // 枚举试探系数 j bool flag = true; // 标志位记录当前方案是否可行 long long ans = j * n + i; // 初始化当前总鱼量 for (long long k = 1; k < n && flag; ++k) { // 进行 N-1 步模拟 if (ans % (n - 1)) { // 判断是否能整除 (N-1) flag = false; // 若无法整除,则标记失败 break; } ans = ans / (n - 1) * n + i; // 更新下一阶段的鱼总量 } if (flag) { // 找到首个合法方案 cout << ans << endl; return 0; } } } ``` --- #### 关键点说明 1. **初始化公式** 初始鱼的数量可以通过设置不同的倍数值来调整范围,从而覆盖所有潜在可能性[^4]。 2. **逐级验证机制** 在每一次试验过程中都需要严格遵循既定规则逐一校验各环节的状态变化情况,只有当全部步骤均无异常发生时才认定此候选答案有效[^3]。 3. **边界处理技巧** 特别注意极端情形下的行为表现,比如仅有两只会东西的小动物或者刚好处于临界点附近的测试样例等特殊场景[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值