第19届PTA天梯赛——L2吉利矩阵

本文讲述了如何解决一个与PTA上整数分解相似的问题,利用深度优先搜索和回溯方法,通过遍历矩阵并优化剪枝策略,最终在460毫秒内AC。作者分享了关键思路、细节和代码实现。

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

       

        

        遗憾的是,比赛中没有全部AC。

        现在想出来了,和之前做过的一道题很类似,那道题也是PTA上的题目(整数分解为若干项之和),链接放下面了,大家可以看懂这道题之后去尝试做一下。

PTA | 程序设计类实验辅助教学平台

为什么说类似呢,其实都是深搜+回溯。

我讲一下大概得思路以及注意的细节,然后大家看看代码估计就可以懂啦

当然里面还有一些剪枝,一开始没有优化剪枝会有两个超时(测试点4,5)

思路就是去遍历每一个点,遍历的时候我们给它进行赋值(0~L)即可,然后往下一个点遍历就好了···

第一个细节,题目说的是非负整数(包括0哦)

这里用了一个比较好用的技巧,大家可以记住,以后用起来很方便

样例是3*3的矩阵,我们给他们编号0~8 从左到右 从上倒下

当得到编号i时,我们可以对它进行变换,找到它所在的行列值,具体做法

        x=i/3;y=i%3;大家可以自己算几个,没问题的

当我们遍历到i==M(M是N*N)也就是最后一个的下一个时,我们就赋值完了一种矩阵,这时我们可以去判断是否满足条件,这里用到了hang[],lie[]数组记录各行各列的值,很容易想到,我只要判断他们是否都等与L即可,只要不等于就直接返回,否则最后记得加1记录下来。

这样太慢了,没有剪枝,判断还浪费了O(N)的时间,当然下面的代码就超时了,超时2个测试点

也不能说没有剪枝(有一个小小的剪枝,你们发现没)

    if(hang[x]>L||lie[y]>L)
        return;

#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int L,N,M;
int fz[10][10];
int hang[10];
int lie[10];
int sum=0;
void dfs(int i)
{
    if(i==M)
    {
        for(int j=0;j<N;j++)
            if(hang[j]!=L||lie[j]!=L)
                return;
        sum++;
        return;
    }
    int x=i/N,y=i%N;
    if(hang[x]>L||lie[y]>L)
        return;
    for(int j=0;j<=L;j++)
    {
        hang[x]+=j;
        lie[y]+=j;
        dfs(i+1);
        hang[x]-=j;
        lie[y]-=j;
    }
}
int main()
{
    cin>>L>>N;
    M=pow(N,2);
    memset(hang, 0, sizeof(hang));
    memset(lie, 0, sizeof(lie));
    dfs(0);
    cout<<sum;
}

超时就优化一下吧,做做剪枝操作,把判断操作下放到每个行、列的最后一个位置(不理解没关系,其实说的就是这段代码)

        if(x==N-1)
        {
            pl=true;
            j=L-lie[y];
        }
        else if(y==N-1)
        {
            pl=true;
            j=L-hang[x];
        }

大家想一想 当我们到的是的最后一个值时(y==N-1),它的值还有选择吗,是不是就是L-hang[y],使得这一行的值加起来等于L 对吧~     想想 是没问题的

第二个细节出现了,我第一次写,就写反了

错误代码:

        if(x==N-1)
        {
            pl=true;
            j=L-hang[x];
        }
        else if(y==N-1)
        {
            pl=true;
            j=L-lie[y];
        }

有区别嘛~   当x==N-1时指的是最后一行的每一列的最后一个位置 所以我们需要用到lie[y],而不要想当然得认为(x代表行,我看到x就认为是和hang[]有关系的,比如我~ 看了好多遍,(耶? 没问题啊我去,思路剪枝都没问题,怎么答案错误)终于还是让我找到bug了)

具体实现看完整代码吧~没有注释(我知道是坏习惯,但是我太懒了,一般简单的从来不写~,大家还是写注释养成习惯较好哈)

#include<iostream>
#include<string.h>
#include<cmath>
using namespace std;
int L,N,M;
int hang[4],lie[4];
int sum=0;
void dfs(int i)
{
    if(i==M)
    {
        sum++;
        return;
    }
    int x=i/N,y=i%N;
    for(int j=L;j>=0;j--)
    {
        if(hang[x]+j>L||lie[y]+j>L)
            continue;
        bool pl=false;
        if(x==N-1)
        {
            pl=true;
            j=L-lie[y];
        }
        else if(y==N-1)
        {
            pl=true;
            j=L-hang[x];
        }
        hang[x]+=j;
        lie[y]+=j;
        dfs(i+1);
        hang[x]-=j;
        lie[y]-=j;
        if(pl) break;
    }
}
int main()
{
    cin>>L>>N;
    M=pow(N,2);
    memset(hang, 0, sizeof(hang));
    memset(lie, 0, sizeof(lie));
    dfs(0);
    cout<<sum;
    return 0;
}

AC 460ms 搞定La~~~~

大家不懂多多评论区交流,互相请教互相帮助,没准别人一句话就点通你(亲身经历)

 期待和大家共同加油,希望大家不断进步!

### PTA吉利矩阵C++实现 PTA上的吉利矩阵问题通常涉及二维数组的操作以及特定条件下的遍历逻辑。以下是基于常见题目描述的一个可能解法,假设问题是要求在一个给定的矩阵中找到满足某些条件的最大子矩阵。 #### 1. 题目分析 吉利矩阵问题的核心在于如何高效地处理二维数据结构并应用算法来解决问题。常见的任务包括计算最大和、路径规划或其他约束条件下的最优解[^1]。 #### 2. 数据结构设计 为了存储矩阵中的元素,可以使用标准库中的`vector<vector<int>>`作为主要的数据容器。这种动态数组能够灵活适应不同大小的输入矩阵[^2]。 ```cpp #include <iostream> #include <vector> using namespace std; int main() { int n, m; cin >> n >> m; // 输入矩阵尺寸n*m vector<vector<int>> matrix(n, vector<int>(m)); for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ cin >> matrix[i][j]; // 填充矩阵 } } return 0; } ``` 此代码片段展示了基本的矩阵读取操作,为后续更复杂的运算奠定了基础[^3]。 #### 3. 动态规划求解方法 对于寻找吉利矩阵这样的优化问题,动态规划是一种常用的技术。通过构建辅助表记录中间状态的结果,从而减少重复计算提高效率[^4]。 假设立一项规则:定义吉利值为某区域内所有数之积大于零的情况,则可以通过如下方式更新dp表格: ```cpp // 初始化DP表 vector<vector<bool>> dp(n, vector<bool>(m, false)); for (size_t i = 0; i < n; ++i) { for (size_t j = 0; j < m; ++j) { if(matrix[i][j] > 0){ dp[i][j] = true; // 单元格本身即符合条件 }else{ continue; } // 尝试扩展区域 if(i>0 && dp[i-1][j]){ dp[i][j] |= dp[i-1][j]; } if(j>0 && dp[i][j-1]){ dp[i][j] |= dp[i][j-1]; } } } // 输出最终结果... ``` 以上伪代码仅作示意用途,实际编码需依据具体业务需求调整边界条件与转移方程[^5]。 #### 4. 边界情况考虑 任何算法都应充分考虑到极端测试用例的影响,比如当整个矩阵全由负数值构成时该如何响应?或者单行列情形下程序的行为是否正常等问题都需要额外验证[^6]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值