• 一道构造题


    Problem

    给定一个(n imes m)的矩阵,每次可以对矩阵做以下操作:

    1、给矩阵的一行同时加上一个数(k)

    2、给矩阵的一列同时加上一个数(k)

    3、给矩阵的一条对角线同时加上一个数(k)。给定(t),即(forall j-i=t),满足的(a_{i,j})即为一条对角线。

    构造一种方案使得矩阵最后全为0。无解输出-1。

    (n,mleq 10^3)

    Solution

    这是一道构造题,我们来考查操作下不变的关系。

    考查一个(3 imes 3)的矩阵,可以发现:(a_{1,1}-a_{2,1}-a_{1,2}+a_{2,3}+a_{3,2}-a_{3,3})始终不变!

    在三类操作下,变化的值总是能被抵消掉!(将其黑白染色)

    所以只要能填好前两行和前两列,依据以上等式可以将全部矩阵推导出来。

    问题就变成:将前两行前两列通过三种操作变成0,判断剩下位置是否为0。如果为0,则肯定无解;反之则有解。

    那么现在如何将前两行前两列变成0?这个很简单,把(a_{1,1})(a_{2,2})变成0后,对于第一行和第一列的数字,利用操作三变成0;对于第二行第二列,利用一二操作,这样可以不影响到(a_{1,1})(a_{1,2})

    #include <bits/stdc++.h>
    typedef long long LL;
    const int N = 1005;
    int n, m, a[N][N];
    LL x[N], y[N], z[N*2];
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++)
    			scanf("%d", &a[i][j]);
    	x[1] = a[2][2]-a[1][1]; z[n] = -a[2][2];
    	for (int i = 2; i <= n; i++) z[n-i+1] = -(a[i][1]+x[i]), x[i+1] = -(a[i+1][2]+z[n-i+1]);
    	for (int i = 2; i <= m; i++) z[n+i-1] = -(a[1][i]+x[1]+y[i]), y[i+1] = -(a[2][i+1]+z[n+i-1]);
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= m; j++)
    			if (a[i][j]+x[i]+y[j]+z[j-i+n]) { puts("-1"); return 0; }
    	printf("%d
    ", 2*(n+m)-1);
    	for (int i = 1; i <= n; i++) printf("1 %d %lld
    ", i, x[i]);
    	for (int i = 1; i <= m; i++) printf("2 %d %lld
    ", i, y[i]);
    	for (int i = 1; i <= n+m-1; i++) printf("3 %d %lld
    ", i-n, z[i]);
    	return 0;
    }
    
  • 相关阅读:
    在老王指导下第一次完成购物车!!!
    自己封装的getElementByClassName函数,解决部分浏览器不兼容的问题
    第一次用js实现window10日历----动态的哟!
    第一次完成注册页面!分享一下,哈哈哈!
    array和string的方法
    js关于函数全局变量和局部变量的区分
    CSS3的3D效果样式transform属性中的rotate3d
    css中的 权重
    margin padding 和边框线的使用
    图片bug
  • 原文地址:https://www.cnblogs.com/ac-evil/p/14015394.html
Copyright © 2020-2023  润新知