zoukankan      html  css  js  c++  java
  • Codeforces 816C/815A

    传送门:http://codeforces.com/contest/816/problem/C

    本题是一个模拟问题。

    有一个n×m的矩阵。最初,这个矩阵为零矩阵O。现有以下操作:

    a.行操作“row i”:对第i(1≤i≤n)行的所有元素加一;

    b.列操作“col j”:对第j(1≤j≤m)列的所有元素加一。

    经过有限次操作,矩阵变为$G=(g_{i,j})_{m*n}$。

    对于给定的矩阵G,试判断G是否可以由零矩阵O通过有限次的“行操作”和“列操作”生成?若可以,则求一个操作步数最小的方案;否则,返回-1。

    考虑一个矩阵。假定其首先进行“行操作”,再进行“列操作”。设对第i行的操作次数为row[i],对第j行的操作次数为col[j],则有g[i][j]=row[i]+col[j]。如此,求解row[]和col[]数组即可。

    假设零矩阵O经过“行操作”后变为矩阵T,再由矩阵T经过“列操作”变为矩阵G。则row[i]取矩阵G中第i行的最小元素,col[j]取矩阵G-T中第j行的最小元素。若零矩阵O可以通过row[]和col[]数组对应的操作变为矩阵G,则row[]和col[]数组对应的操作方案为最优操作方案;否则,可行的操作方案不存在。

    row[]和col[]数组的求解在程序实现上可以通过逆向模拟的方法。

    值得注意的是,对于一个给定行列数目的矩阵,若其行数不大于列数,则首先进行“行操作”,再进行“列操作”是最佳选择;否则,首先进行“列操作”,再进行“行操作”是最佳选择。

    参考程序如下:

    #include <stdio.h>
    #include <stdlib.h>
    #define SIZE 100
    #define MAX_VAL 1000
    
    int n, m, cnt = 0;
    int g[SIZE][SIZE];
    int row[SIZE], col[SIZE];
    
    void row_operate(void)
    {
        for (int i = 0; i < n; i++) {
            row[i] = MAX_VAL;
            for (int j = 0; j < m; j++)
                if (g[i][j] < row[i]) row[i] = g[i][j];
            for (int j = 0; j < m; j++)
                g[i][j] -= row[i];
            cnt += row[i];
        }
    }
    
    void col_operate(void)
    {
        for (int j = 0; j < m; j++) {
            col[j] = MAX_VAL;
            for (int i = 0; i < n; i++)
                if (g[i][j] < col[j]) col[j] = g[i][j];
            for (int i = 0; i < n; i++)
                g[i][j] -= col[j];
            cnt += col[j];
        }
    }
    
    int main(void)
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                scanf("%d", &g[i][j]);
        if (n <= m) {
            row_operate();
            col_operate();
        }
        else {
            col_operate();
            row_operate();
        }
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (g[i][j]) {
                    printf("-1
    ");
                    exit(0);
                }
        printf("%d
    ", cnt);
        for (int i = 0; i < n; i++)
            for (int k = 0; k < row[i]; k++)
                printf("row %d
    ", i + 1);
        for (int j = 0; j < m; j++)
            for (int k = 0; k < col[j]; k++)
                printf("col %d
    ", j + 1);
        return 0;
    }
  • 相关阅读:
    python爬虫23 | 手机,这次要让你上来自己动了。这就是 Appium+Python 的牛x之处
    python爬虫22 | 以后我再讲python「模拟登录」我就是狗
    python爬虫21 | 对于b站这样的滑动验证码,不好意思,照样自动识别
    phpcms 之 日期时间标签的调用
    phpcms 友情链接的调用
    在网页中嵌入百度地图的步骤(转)
    jquery 怎么取select选中项 自定义属性的值
    PHP实现根据银行卡号判断银行
    数据库基础
    从输入网址到显示网页的过程中发生了什么?(转自88旧港)
  • 原文地址:https://www.cnblogs.com/siuginhung/p/7745683.html
Copyright © 2011-2022 走看看