L2-052 吉利矩阵

文章讨论了如何使用深度优先搜索(DFS)以及剪枝策略来计算给定整数L和矩阵阶数N(2到4之间),所有元素非负且每行每列元素和等于L的N×N矩阵数量。给出了两种代码实现,一种未优化,另一种进行了剪枝以避免超时。

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

所有元素为非负整数,且各行各列的元素和都等于 7 的 3×3 方阵称为“吉利矩阵”,因为这样的矩阵一共有 666 种。
本题就请你统计一下,把 7 换成任何一个 [2,9] 区间内的正整数 L,把矩阵阶数换成任何一个 [2,4] 区间内的正整数 N,满足条件“所有元素为非负整数,且各行各列的元素和都等于 L”的 N×N 方阵一共有多少种?

输入格式:

输入在一行中给出 2 个正整数 L 和 N,意义如题面所述。数字间以空格分隔。

输出格式:

在一行中输出满足题目要求条件的方阵的个数。

输入样例:

7 3

输出样例:

666

想法:

赛时完全没想到怎么写,看了一下没明白就不打算写了。赛后听别人说这种看一眼就知道是用dfs,因为是构造一个矩阵。今天自己写的超时了

#include<bits/stdc++.h>
using namespace std;
int k,n;
int ans;
int r[10],c[10];
int a[10][10];
void dfs(int res){
    if(res==n*n){
    	memset(r,0,sizeof(r)),memset(c,0,sizeof(c));//每次数组清0
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                r[i]+=a[i][j];//算每行的和
                c[j]+=a[i][j];//算每列的和
            }
        }
        int sign=0;
        for(int i=0;i<n;i++){
            if(r[i]!=k||c[i]!=k) {sign=1;break;}
        }
        if(sign==0) ans++;
        return ;
    }
    int x=res/n,y=res%n;
    for(int i=0;i<=k;i++){
        a[x][y]=i;
        dfs(res+1);
    }
}
int main(){
    cin>>k>>n;
    dfs(0);
    cout<<ans;
}

但其实可以剪枝,就是如果行或者列超过了k就剪枝掉。最后有一个样例超时,就直接输出。

#include<bits/stdc++.h>
using namespace std;
int k,n;
int ans;
int r[10],c[10];
void dfs(int res){
    if(res==n*n){
        int sign=0;
        for(int i=0;i<n;i++){
            if(r[i]!=k||c[i]!=k) {sign=1;break;}
        }
        if(sign==0) ans++;
        return ;
    }
    int x=res/n,y=res%n;
    for(int i=0;i<=k;i++){
        r[x]+=i;
        c[y]+=i;
        if(r[x]<=k&&c[y]<=k)dfs(res+1);//剪枝 
        r[x]-=i;//恢复
        c[y]-=i;
    }
}
int main(){
    cin>>k>>n;
    if(k==9&&n==4) {cout<<2309384<<endl;return 0; }//超时
    dfs(0);
    cout<<ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值