https://www.codechef.com/problems/MTRNSFRM

我只能说codechef的题好劲爆,这题居然是easy的题,太可怕了。而且还有一点就是codechef的题解很难看懂╮( ̄▽ ̄")╭

这题可以这样做,首先把两个矩阵合并在一起,然后就是变成了在一个矩阵C中,操作行和列的+1或者-1,最终使得整个矩阵为0。

那么。对于每一行,的操作,我设为row[i],意思就是这一行进行的是什么操作,要么+,要么-,不可能又加又减的,因为都是整行的操作。然后同理设出col[j]。

然后,如果有解,那么需要每个c[i][j] + row[i] + col[j] == 0恒成立。

在上面的方程中,有两个未知数,因为其是互相独立的,那么特殊值一个先,先设i = 1

有col[j] = -row[1] - c[1][j]  ① (这个就是col[j]的方程,因为只有j这个未知数)row[1]可以暴力出来,或者二分出来,反正是常数,那么带入去原来的式子,有:row[i] = row[1] + c[1][j] - c[i][j]

同样是因为独立,所以特殊值那个j = 1,所以row[i] = row[1] + c[1][1] - c[i][1] ②

有了上面两条式子,要判定c[i][j] + row[i] + col[j] == 0是否成立就简单了,带进去即可。

求解:

解的大小是sigma abs(row[i])   + sigma abs(col[j])

目标是最小化这个函数。

其中有一个x(row[1])是还没确定的呢。

把公式拆开,就是sigma(abs(c[i][1] - c[1][1] - x)) + sigma(-c[1][j] - x)

那么就是求一个点x,到c[i][1] - c[1][1]   和  -c[1][j]  这n + m个点的总和最小。

中间值即可。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 1e5 + ;
vector<LL>a[maxn], ta[maxn];
vector<LL>vc;
void work() {
int n, m;
scanf("%d%d", &n, &m);
vc.clear();
for (int i = ; i <= n; ++i) {
a[i].clear();
ta[i].clear();
a[i].push_back();
}
for (int i = ; i <= ; ++i) {
for (int j = ; j <= n; ++j) {
for (int k = ; k <= m; ++k) {
LL x;
if (i == ) {
scanf("%lld", &x);
a[j].push_back(x);
} else {
scanf("%lld", &x);
a[j][k] -= x;
}
}
}
}
for (int i = ; i <= n; ++i) ta[i] = a[i];
for (int i = ; i <= n; ++i) {
for (int j = ; j <= m; ++j) {
if (a[i][j] + a[][] - a[i][] - a[][j] != ) {
cout << - << endl;
return;
}
}
}
vc.push_back(-((1LL) << ));
for (int i = ; i <= n; ++i) {
vc.push_back(a[i][] - a[][]);
}
for (int j = ; j <= m; ++j) {
vc.push_back(-a[][j]);
}
sort(vc.begin(), vc.end());
LL ans = ;
for (int i = ; i < vc.size(); ++i) {
ans += abs(vc[i] - vc[(n + m + ) / ]);
}
cout << ans << endl;
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
int t;
scanf("%d", &t);
while (t--) work();
return ;
}

最新文章

  1. 802.1X基础
  2. springboot使用之三:springboot使用logback日志
  3. 如何防止ElasticSearch集群出现脑裂现象(转)
  4. http://jingyan.baidu.com/article/636f38bb3eb78ad6b8461082.html
  5. 内存泄漏,当您使用的 GetDC 方法和 ReleaseDC 方法 CWnd 类版本
  6. ERROR ITMS-90049错误解决
  7. 深入java并发Lock一
  8. ROM、RAM、DRAM、SRAM和FLASH的区别
  9. sqlmap完成简单的sql注入
  10. C++之异常捕获和处理
  11. IDEA下运行 mybatis报错 Parameter &#39;arg0&#39; not found. Available parameters are [autoRecharge, id, param1, param2]
  12. Python的math模块
  13. java时间计算
  14. python--使用队列结构来模拟烫手山芋的游戏
  15. Linux(CentOS-7) 下载 解压 安装 redis 操作的一些基本命令
  16. 20155208 2006-2007-2 《Java程序设计》第1周学习总结
  17. Beta阶段第二次冲刺
  18. K:图的存储结构
  19. 如何学习sql语言?
  20. linux不重启挂载磁盘安装grub

热门文章

  1. Linux 命令 sudo
  2. 怎样更好的设计你的REST API之基于REST架构的Web Service设计及REST框架实现
  3. oracle获取字符串长度函数length()和lengthb()
  4. 推荐系统(1)--splitting approaches for context-aware recommendation
  5. centos7 配置虚拟交换机(物理交换机truckport设置)(使用brctl)
  6. my.cnf配置详解[转载]
  7. 一些java错误
  8. hashable
  9. SE11 数据表中 日志数据更改 勾选的作用
  10. mysql14---手动备份