洛谷八连测 R4 T3 但有用题解 (思想题)

  题面:

题目描述

给定一个 n ∗ m 个矩阵,矩阵中每个数都是 [1, 12] 内的整数。你可以执行下列两个操作任意多次:

• 指定一行,将该行所有数字 +1.

• 指定一列,将该列所有数字 +1.

如果执行完上述操作之后,矩阵中某个数变成了 3, 6, 9, 12 其中的某一个,我们认为这个数是稳的。

给定初始矩阵,求出任意执行操作之后稳数的最多个数。

输入输出格式

输入格式:
第一行包含两个正整数 n, m。

接下来 n 行,每行 m 个数,描述这个矩阵。

输出格式:
一个整数,表示答案。

输入输出样例

输入样例#1:
3 3
1 2 3
3 2 4
1 2 1
输出样例#1:
7
输入样例#2:
5 5
2 4 6 8 10
1 2 3 4 5
3 4 5 6 7
7 8 9 10 11
5 10 12 3 7
输出样例#2:
20
说明

测试点编号   限制与约束
1        n,m<=2
2        n,m<=5
3~10       n,m<=10

 

  这道题其实是一道送分题,出题人为了暗示这一点把数据出的非常奇怪,题意也只是加法,没有减法,还给了两个SPJ,剩下80分就没有给部分分了。(然而我这个菜鸡还是没想出来,只能打O(12n+m*n*m)大暴力水一水QAQ)

  这道题骗分思路就是直接暴力枚举每行每列每个数加多少,优化一下,可以发现每行或者每列只用加0或1或2这3个数,因为既然加这3个数就可以达到目的,就没必要再加更大的数字,避免超出12的范围,这样一来复杂度就变成O(3n+m*n*m)但并没有什么*用。

  但只要我们从枚举这里下手优化,就可以发现一个奇妙的方法,使得时间复杂度变成O(3n+1*n*m)。

  正解思路:

  我们可以先确定每行(或者每列,这个由自己决定,我是先确定每行)要加多少,再枚举每列(每行)加的数,选取其中的最优值,加入答案,输出即可。

  代码如下:

#include<bits/stdc++.h>
using namespace std;
#define FOR(l,r,i) for(int i=l;i<=r;++i)
const int N=11;
int n,m,ans,a[N][N],c[N][3],d[N];//a[i][j]代表第i行第j列的数字
//c[j][k]代表第j列加上k后满足条件的答案,d[i]代表第i行要加的数。 
template<class T>inline void read(T &x)//读入优化 
{
    x=0;int f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){ f|=(ch=='-'); ch=getchar(); }
    while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    x=f ? -x:x;
    return;
}
inline int check(int x)//判断此时被更改过的点是否越界,是否满足“稳”的条件。 
{
    return x<=12&&(x%3==0?1:0);
}
void DFS(int x)
{
    if(x>n)//已确定所有行的值,开始扫整张图 来确定答案。 
    {
        int res=0;
        FOR(1,m,j)//枚举列。 
        {
            c[j][0]=c[j][1]=c[j][2]=0;//初始化。 
            FOR(1,n,i)FOR(0,2,k)//i代表行,k代表加的数。 
            c[j][k]+=check(d[i]+a[i][j]+k);//判断。 
            res+=max(max(c[j][0],c[j][1]),c[j][2]);//选出其中满足条件最多的那一个。 
        }
        ans=max(ans,res);//加入到答案中。 
        return;
    }
    FOR(0,2,i)
    d[x]=i,DFS(x+1);//确定每行加的值。 
    return;
}
int main()
{
    read(n);read(m);
    FOR(1,n,i)FOR(1,m,j)read(a[i][j]);
    DFS(1);
    printf("%d",ans);
    return 0; 
}

 

转载于:https://www.cnblogs.com/Wujiga/p/7726434.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值