Codeforces 816C/815A - Karen and Game

Posted SiuGinHung

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 816C/815A - Karen and Game相关的知识,希望对你有一定的参考价值。

传送门: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\n");
                exit(0);
            }
    printf("%d\n", cnt);
    for (int i = 0; i < n; i++)
        for (int k = 0; k < row[i]; k++)
            printf("row %d\n", i + 1);
    for (int j = 0; j < m; j++)
        for (int k = 0; k < col[j]; k++)
            printf("col %d\n", j + 1);
    return 0;
}

 

以上是关于Codeforces 816C/815A - Karen and Game的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces 816C 思维

CodeForces 816B 前缀和

CodeForces 816B Karen and Coffee(前缀和,大量查询)

Karen and Game CodeForces - 816C (暴力+构造)

CodeForces - 816C Karen and Game(简单模拟)

[Codeforces 816A]Karen and Morning