Vestigium-Google CodeJam 2020资格回合问题1解决方案

Problem statement:

问题陈述:

Vestigium means "trace" in Latin. In this problem we work with Latin squares and matrix traces.

Vestigium在拉丁语中表示“痕迹”。 在此问题中,我们使用拉丁方和矩阵迹线。

The trace of a square matrix is the sum of the values on the main diagonal (which runs from the upper left to the lower right).

方阵的轨迹是主对角线(从左上角到右下角)上的值之和。

An N-by-N square matrix is a Latin square if each cell contains one of N different values, and no value is repeated within a row or a column. In this problem, we will deal only with "natural Latin squares" in which the N values are the integers between 1 and N.

如果每个单元格包含N个不同值之一,并且在行或列中没有重复值,则N × N方阵是拉丁方阵。 在这个问题中,我们将只处理“自然拉丁方”,其中N值为1到N之间的整数。

Given a matrix that contains only integers between 1 and N, we want to compute its trace and check whether it is a natural Latin square. To give some additional information, instead of simply telling us whether the matrix is a natural Latin square or not, please compute the number of rows and the number of columns that contain repeated values.

给定一个仅包含1到N之间的整数的矩阵,我们想计算其轨迹并检查它是否为自然的拉丁方。 为了提供一些其他信息,而不是简单地告诉我们矩阵是否是自然的拉丁正方形,请计算包含重复值的行数和列数。

Input:

输入:

The first line of the input gives the number of test cases, T. T test cases follow. Each starts with a line containing a single integer N: the size of the matrix to explore. Then, N lines follow. The i-th of these lines contains N integers Mi,1 ,Mi,2 ...,Mi,N. Mi,j is the integer in the i-th row and j-th column of the matrix.

输入的第一行给出测试用例的数量T。 随后是T测试用例。 每个都以包含单个整数N的行开始: N :要探索的矩阵的大小。 然后,跟随N行。 这些行中的第i个包含N个整数M i,1 ,M i,2 ...,M i,N 。 M i,j是矩阵的第i行和第j列中的整数。

Output:

输出:

For each test case, output one line containing Case #x: k r c, where x is the test case number (starting from 1), k is the trace of the matrix, r is the number of rows of the matrix that contain repeated elements, and c is the number of columns of the matrix that contain repeated elements.

对于每个测试用例,输出包含Case# x的一行:krc ,其中x是测试用例编号(从1开始), k是矩阵的迹线, r是包含重复元素的矩阵的行数, c是包含重复元素的矩阵的列数。

Constraints:

限制条件:

1 ≤ T ≤ 100.
2 ≤ N ≤ 100.
1 ≤ Mi,j ≤ N,for all i,j.

Example:

例:

Input:
3 #no of test cases
4 # value of N
1 2 3 4 # ith row
2 1 4 3
3 4 1 2
4 3 2 1
4
2 2 2 2
2 3 2 3
2 2 2 3
2 2 2 2
3
2 1 3
1 3 2
1 2 3

Output:
Case #1: 4 0 0
Case #2: 9 4 4
Case #3: 8 0 2

Explanation:

说明:

In Example #1, the input is a natural Latin square, which means no row or column has repeated elements. All four values in the main diagonal are 1, and so the trace (their sum) is 4.

在示例1中,输入是自然的拉丁方格,这意味着行或列中没有重复的元素。 主对角线上的所有四个值均为1,因此迹线(它们的总和)为4。

In Example #2, all rows and columns have repeated elements. Notice that each row or column with repeated elements is counted only once regardless of the number of elements that are repeated or how often they are repeated within the row or column. In addition, notice that some integers in the range 1 through N may be absent from the input.

在示例2中,所有行和列都有重复的元素。 注意,具有重复元素的每一行或每一列仅计数一次,而不管重复元素的数量或在行或列中重复元素的频率。 另外,请注意,输入中可能缺少1到N范围内的某些整数。

In Example #3, the leftmost and rightmost columns have repeated elements.

在示例#3中,最左边和最右边的列具有重复的元素。

Source: Qualification Round 2020 - Code Jam 2020 - Vestigium

资料来源: 2020年资格巡回赛-2020年《果酱大战》-Vestigium

Solution

Before discussing the solution, I want to mention a few points here on Google Codejam. Codejam is similar to competitive programming. Here time complexity is not only the measure. Say your code has a time complexity of O(n) but the loop runs twice and the second one is redundant. This may lead to TLE through your time complexity is optimal. So few things we need to optimize is:

在讨论解决方案之前,我想在Google Codejam上提几点。 Codejam与竞争性编程类似。 在这里,时间复杂度不仅是度量。 假设您的代码的时间复杂度为O(n),但是循环运行两次,第二个循环是多余的。 这可能导致TLE通过您的时间复杂度是最佳的。 我们需要优化的几件事是:

  1. Fast i/o- use fast i/o to reduce the time (refer to fast i/o article of our website)

    快速I / O-使用快速I / O以减少时间(请参阅我们网站上的快速I / O文章)

  2. Loop optimization: Refactor your code so that there are no redundant loops

    循环优化:重构代码,以确保没有多余的循环

  3. Avoid functions as this may lead to more time taken (using the function is always recommended to write production-level code, but competitive programming is different)

    避免使用函数,因为这可能会花费更多时间(始终建议使用该函数编写生产级代码,但竞争性编程会有所不同)

So here I haven't used any function and have used fast i/o. {Please refer to my code for details.

所以在这里我没有使用任何功能并且使用了快速的I / O。 {请参阅我的代码以获取详细信息。

Now back to the solution.

现在回到解决方案。

1) Computing trace

1)计算轨迹

Diagonal means a[i][i]

对角表示a [i] [i]

Trace of a matrix means sum of the diagonal which is sum(a[i][i])

矩阵的轨迹表示对角线之和 ,即sum(a [i] [i])

I have computed the trace while taking input as part of loop optimization

在将输入作为循环优化的一部分时,我已经计算了跟踪

While taking the input while row==column, I have added the input to my cumulative sum and after input taking is done, I have my trace value ready too.

row == column的同时获取输入时,我已将输入添加到累积总和中,完成输入获取后,我也准备好跟踪值。

2) Checking number of rows having duplicate entry

2)检查重复条目的行数

I have done this too while taking input. While taking input for each row, I have kept a map to check whether the input is already present there or not. If present, mark that row as duplicate and we are done for that row, for further inputs we will not check anymore to reduce time. This can be done using a flag variable.

我在接受输入时也这样做了。 在获取每一行的输入时,我保留了一张地图以检查输入是否已经存在。 如果存在,则将该行标记为重复行,然后完成该行的操作,对于其他输入,我们将不再进行检查以减少时间。 这可以使用标志变量来完成。

So, By the time I took my input, I have two things ready. One is trace and another is the count of duplicate rows.

因此,当我接受输入时,我已经做好了两件事。 一个是跟踪,另一个是重复行的计数。

3) Checking number of rows having duplicate entry

3)检查重复条目的行数

For this thing, I was unable to compute while taking the input. As I was taking input row-wise, the column was not ready for me until my last row input. I could have stored additionally each column but that would be not so efficient considering. To compute this using another loop similar I did for row duplicate checking. For each column, we will use a map and check if any duplicate value has arrived r not. If any time, we find a duplicate, just mark that column as duplicate as proceed to the next column.

为此,我无法在输入时进行计算。 当我逐行进行输入时,直到我最后一行输入时,该列才为我准备好。 我本可以另外存储每列,但是考虑起来并不是那么有效。 为了使用另一个循环来计算它,我做了行重复检查。 对于每一列,我们将使用一个映射并检查是否有任何重复的值到达或没有到达。 如果有时间,我们会找到重复的记录,只需将该列标记为重复,就可以继续进行下一列。

C++ Implementation:

C ++实现:

#include <bits/stdc++.h>
using namespace std;

#define lli long long int

int main()
{
    // fast io
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    
    int t;
    cin >> t;
    
    for (int test_case = 1; test_case <= t; test_case++) {
        int n;
    
        //input N
        cin >> n;
    
        int** arr = (int**)(malloc(sizeof(int*) * n));
    
        //to calculate trace
        lli sum = 0;
    
        //to calculate duplicate rows
        int row = 0;
    
        for (int i = 0; i < n; i++) {
            arr[i] = (int*)(malloc(sizeof(int) * n));
            map<int, int> mymap;
            bool flag = false;
            for (int j = 0; j < n; j++) {
                cin >> arr[i][j];
                //calculating trace of the matrix
                if (i == j)
                    sum += arr[i][j];
                //to check whether duplicate exists in this column
                if (flag == false && mymap.find(arr[i][j]) != mymap.end()) {
                    row++;
                    flag = true;
                }
                if (flag == false)
                    mymap[arr[i][j]]++;
            }
        }
    
        // to calculate duplicate columns
        int col = 0;
        for (int i = 0; i < n; i++) {
            map<int, int> mymap;
            bool flag = false;
            for (int j = 0; j < n; j++) {
                // to check whether duplicate exists in this column
                if (flag == false && mymap.find(arr[j][i]) != mymap.end()) {
                    col++;
                    flag = true;
                    // once duplicate found simply break
                    break;
                }
                if (flag == false)
                    mymap[arr[j][i]]++;
            }
        }
        cout << "Case #" << test_case << ": " << sum << " " << row << " " << col << endl;
    }
    
    return 0;
}

Output:

输出:

3
4
1 2 3 4
2 1 4 3
3 4 1 2
4 3 2 1
Case #1: 4 0 0
4
2 2 2 2
2 3 2 3
2 2 2 3
2 2 2 2
Case #2: 9 4 4
3
2 1 3
1 3 2
1 2 3
Case #3: 8 0 2


翻译自: https://www.includehelp.com/icp/vestigium-google-codejam-2020-qualification-round-problem1-solution.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值