IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 代码源每日一题 div1 #807 矩阵操作 -> 正文阅读

[数据结构与算法]代码源每日一题 div1 #807 矩阵操作

代码源每日一题 div1 #807 矩阵操作

题意

给你一个二维矩阵,每次可以对一行或者一列加1(modk),问,最少需要多少次操作,能让整个矩阵变成全0。

思路

首先,我们先考虑对每行/列加这个操作,很容易想到,用 r i r_i ri?表示给第i行加的次数, c i c_i ci?表示给第i列加了多少次。那么,我们需要求一个约束条件为 r i + c i + a i j = 0 ( m o d k ) r_i+c_i+a_{ij}=0(modk) ri?+ci?+aij?=0(modk) ∑ ( r i + c i ) \sum(r_i+c_i) (ri?+ci?)的最小正整数解。

先考虑什么情况下有解,稍微观察下可以发现: r i 和 c i r_i和c_i ri?ci?总共有n+m个未知数,而方程有 n ? m n*m n?m

这就提示我们,里面有很多方程都是线性相关的,也就是说,我们可以消除掉一些方程!

现在尝试一下消除,我们不妨假设 r 1 r_1 r1?是已知的,那么 c j = ? r 1 ? a 1 j ( m o d k ) c_j=-r_1-a_{1j}(modk) cj?=?r1??a1j?(modk)。这样我们便求出了所有的 c j c_j cj?。可以得出 c 1 = ? r 1 ? a 11 ( m o d k ) c_1=-r_1-a_{11}(modk) c1?=?r1??a11?(modk)

因为c1已经求出来了,我们可以求出所有的 r i r_i ri?,与上面类似 r i = ? c 1 ? a i 1 ( m o d k ) = r 1 + a 11 ? a i 1 r_i=-c_1-a_{i1} (modk)=r_1+a_{11}-a_{i1} ri?=?c1??ai1?(modk)=r1?+a11??ai1?

r i r_i ri? c i c_i ci?代入 r i + c i + a i j = 0 ( m o d k ) r_i+c_i+a_{ij}=0(modk) ri?+ci?+aij?=0(modk),可以发现 r 1 r_1 r1?可以消掉!得到 a 11 ? a i 1 ? a 1 j + a i j = 0 ( m o d k ) a_{11}-a_{i1}-a_{1j}+a_{ij}=0(modk) a11??ai1??a1j?+aij?=0(modk),所以只要对于所有的数字检验一下这个等式的成立性,就可以求出是否有解了。

那么继续考虑第二个问题,怎么求一个最优解 ∑ ( r i + c i ) \sum(r_i+c_i) (ri?+ci?)

先来个结论, r i r_i ri?或者 c i c_i ci?里面必定有一个为0。

证明:假设最优解中, r i r_i ri? c i c_i ci?全都不为0。

  • n > = m n >= m n>=m, 可以对所有的 r i ? 1 , c i + 1 r_i-1,c_i+1 ri??1ci?+1,那么整个矩阵的 a i j a_{ij} aij?都不变,而且操作次数减少了 n ? m > = 0 n-m>=0 n?m>=0次。会使得结果不会变差,甚至变得更好
  • n < m n < m n<m, 可以对所有的 r i + 1 , c i ? 1 r_i+1,c_i-1 ri?+1ci??1,那么整个矩阵的 a i j a_{ij} aij?都不变,而且操作次数减少了 m ? n > 0 m-n>0 m?n>0次。会使得结果变好。

我们可以做上面两种操作,直到 c i , r i c_i, r_i ci?,ri?有一个为0,并且解更优。矛盾!所以结论得证。

那么有一个为0有什么用呢?

我们不妨假设有一个 r i r_i ri?为0,根据等式 r i + c i + a i j = 0 ( m o d k ) r_i+c_i+a_{ij}=0(modk) ri?+ci?+aij?=0(modk),我们可以求出所有的 c i c_i ci?,再代入一次进而再求出所有的 r i r_i ri?,这样就可以求出一个解了。

列的做法同理,我们的做法就是,暴力枚举哪一行/列的操作次数为0即可。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10, M = 2 * N;  
typedef long long LL;
typedef pair<int,int> PII;
using tp = tuple<int,int,int>;
bool multi = false;

int n, m, k;
int a[N][N];
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return f*x;
}
int mod(int x, int y = k) {
    return (x % y + y) % y;
}
bool check() {

    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++)
            if(mod(a[1][1] - a[1][j] - a[i][1] + a[i][j]) != 0) return false;
    }
    return true;
}

//第x行不发生变化, 那么可以算出c1, 再算出所有的ri
LL cal1(int x) {
    int c1 = mod(-a[x][1]);
    LL res = 0;
    for(int i = 1; i <= n; i++) res += mod(-a[i][1] - c1);
    for(int i = 1; i <= m; i++) res += mod(-a[x][i]);
    return res;
}

//第x列不发生变化, 那么可以算出r1, 再算出所有的ci
LL cal2(int x) {
    int r1 = mod(-a[1][x]);
    LL res = 0;
    for(int i = 1; i <= n; i++) res += mod(-a[i][x]);
    for(int i = 1; i <= m; i++) res += mod(-r1 - a[1][i]);
    return res;
}

void solve() {
    n = read(), m = read(), k = read();
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++) a[i][j] = read();
    
    if(!check()) {
        puts("-1");
        return;
    }
    
    LL res = 1e18;
    for(int i = 1; i <= n; i++) res = min(res, cal1(i));
    for(int i = 1; i <= m; i++) res = min(res, cal2(i));
    cout << res << endl;
}   

int main()
{
#ifdef ONLINE_JUDGE
#else 
    freopen("I.txt", "r", stdin);
#endif
    int T = 1;
    if(multi) cin >> T;
    while(T--) solve();
    return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:57:51  更:2022-05-01 15:58:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:19:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码