Sunday, June 10, 2007

Penyisihan Indonesia National Contest 2007 :: Problem A - The Chosen Sub Matrix

ACM/ICPC Indonesia National Contest 2007 - Qualification

Problem A

The Chosen Sub Matrix

Time Limit: 1s


From a given N x N matrix, you should find an M x M sub matrix which has the least distinct element in it. If there are more than one sub matrixes which have the same number of distinct elements then compare each element in descending order and choose one that has the first highest element. If all of distinct elements of all sub matrixes are the same, chose one with the least row index, and then the least column index. The matrix index starts at 1.

For example, given a 4x4 matrix:
3 9 9 9
3 9 9 2
3 9 9 2
2 5 5 2

Then, the possible sub matrixes of 3x3 are:
3 9 9
3 9 9
3 9 9
S1
9 9 9
9 9 2
9 9 2
S2
3 9 9
3 9 9
2 5 5
S3
9 9 2
9 9 2
5 5 2
S4
Sub matrix S1 has 2 distinct elements: 9 and 3;
Sub matrix S2 has 2 distinct elements: 9 and 2;
Sub matrix S3 has 4 distinct elements: 9, 5, 3, and 2;
Sub matrix S4 has 3 distinct elements: 9, 5, and 2.
Sub matrixes are ranked using the rules above and give result as S1, S2, S4, and then S3.
Which means the chosen sub matrix is S1.


Input Specification

The first line of each case contains two integers, N (1<=N<=10) the size of matrix, and M (1<=M<=N) the size of sub matrix to be chosen. In the next N lines, each contains N integers (each separated by a space) that represent the matrix. Each element in the matrix should be between 0 and 9 inclusively.


Output Specification

For each case you should output in a single line, the top-left index (row and column, separated by a single space) of the chosen sub matrix.


Sample Input

4 3
3 9 9 9
3 9 9 2
3 9 9 2
2 5 5 2
10 2
1 5 7 8 2 3 3 3 1 7
2 2 3 6 3 7 3 2 3 1
5 9 3 5 7 0 4 6 9 1
1 0 3 4 2 6 4 3 9 0
7 4 9 9 5 4 6 2 1 5
5 6 9 9 6 6 3 8 0 8
4 3 3 5 2 1 7 6 4 1
6 5 9 5 0 3 1 8 8 6
2 2 2 8 0 1 3 5 9 0
3 6 4 2 3 3 0 2 0 0

Sample Output

1 1
5 3


Problem Setter: Bong Win Ce



Pembahasan Problem A - The Chosen Sub Matrix

Anda diberikan matrix N x N berisikan angka dari 0 sampai 9. Anda harus "memilih" sub-matrix M x M yang mempunyai elemen berbeda terkecil. Jika ada sub-matrix yang mempunyai elemen berbeda terkecil yang sama, maka anda harus memilih yang mempunyai elemen terbesar yang tidak sama. Jika masih seri juga, maka pilih yang row nya terkecil, lalu column terkecil.

Algorithm untuk problem ini juga straight forward: cari satu-per-satu diantara semua sub-matrix M x M, update hasil kalau ketemu yang lebih bagus. Anda bisa lihat implementasi algoritma ini dibawah (dalam C maupun Java).

#include <stdio.h>

typedef struct {
    int row, col;    // posisi (row,col) dari Square M x M
    int nums[10];    // num[i] == 1 kalau ada angka i di Square ini,
                     // kalau tidak maka num[i] == 0
                     // dimana i adalah angka antara 0..9
} Square;

// menghitung kemunculan angka i dalam array nums
int count_distinct(int nums[10]){
    int i=0,ret=0;
    for (i=0; i<10; i++)
        if (nums[i]) ret++;
    return ret;
}

// membandingkan dua Square sesuai yang diminta soal
// return true kalau sa lebih bagus dari pada sb
int better(Square *sa, Square *sb){
    int distinct_a = count_distinct(sa->nums);
    int distinct_b = count_distinct(sb->nums);
    int i;

    // pertama tama, bandingkan jumlah angka yang berbeda
    if (distinct_a != distinct_b)
        return distinct_a < distinct_b;

    // kedua, bandingkan kemunculan element tertinggi
    for (i=9; i>=0; i--)
        if (sa->nums[i] != sb->nums[i])
            return sb->nums[i] < sa->nums[i];

    // ketiga, bandingkan baris
    if (sa->row != sb->row) return sa->row < sb->row;

    // perbandingan terakhir adalah kolom
    return sa->col < sb->col;
};


int N,M,arr[10][10];

Square get_square(int r, int c){
    Square square;
    int i,j;

    square.row = r;
    square.col = c;

    for (i=0; i<10; i++)
        square.nums[i] = 0;

    for (i=0; i<M; i++)
        for (j=0; j<M; j++)
            square.nums[arr[r+i][c+j]] = 1;

    return square;
}

int main(){
    int i,j;

    while (scanf("%d %d",&N,&M)!=EOF){
        for (i=0; i<N; i++)
            for (j=0; j<N; j++)
                scanf("%d",&arr[i][j]);

        Square chosen = get_square(0,0);

        for (i=0; i+M<=N; i++)
            for (j=0; j+M<=N; j++){
                Square current = get_square(i,j);
                if (better(&current, &chosen))
                    chosen = current;
            }

        // print square yang terpilih
        printf("%d %d\n",chosen.row+1, chosen.col+1);
    }
}
import java.io.*;
import java.util.*;

public class Matrix {
    int[][] arr = new int[10][10];
    int N, M;

    class Square implements Comparable<Square> {
        int row, col;    // posisi (row,col) dari Square M x M

        int[] nums;      // nums[i] == 1 kalau ada angka i di Square ini,
                         // kalau tidak maka nums[i] == 0
                         // dimana i adalah angka antara 0..9

        // meng-inisialisai data untuk Square pada posisi[r][c]
        public Square(int r, int c){
            row = r;
            col = c;
            nums = new int[10]; // ter-inisialisasi sendiri dengan 0

            // mengisi nums[i] dengan 1 jika ada angka i di Square ini,
            // kalau tidak ada maka nums[i] = 0
            for (int i=0; i<M; i++)
                for (int j=0; j<M; j++)
                    nums[arr[r+i][c+j]] = 1;
        }
    

        // menghitung kemunculan angka i dalam array nums
        int distinctCount(){
            int ret = 0;
            for (int i=0; i<10; i++)
                if (nums[i]==1) ret++;
            return ret;
        }

        // membandingkan dua Square sesuai yang diminta soal
        public int compareTo(Square that){
            int thisDistinct = this.distinctCount();
            int thatDistinct = that.distinctCount();

            // pertama tama, bandingkan jumlah angka yang berbeda
            if (thisDistinct != thatDistinct)
                return thisDistinct - thatDistinct;

            // kedua, bandingkan kemunculan tertinggi
            for (int i=9; i>=0; i--)
                if (this.nums[i] != that.nums[i])
                    return that.nums[i] - this.nums[i];

            // ketiga, bandingkan baris
            if (this.row != that.row) return this.row - that.row;

            // perbandingan terakhir adalah kolom
            return this.col - that.col;
        }
    }

    public void solve(){
        Scanner scan = new Scanner(System.in);

        // baca input selama masih ada integer berikutnya
        while (scan.hasNextInt()){
            N = scan.nextInt(); // baca N
            M = scan.nextInt(); // baca M

            // membaca matrix N x N ke variable arr
            for (int i=0; i<N; i++)
                for (int j=0; j<N; j++)
                    arr[i][j] = scan.nextInt();

            Square chosen = new Square(0,0);

            for (int i=0; i+M<=N; i++)
                for (int j=0; j+M<=N; j++){
                    Square current = new Square(i,j);
                    if (current.compareTo(chosen) < 0)
                        chosen = current;
                }

            // output square yang terpilih
            System.out.printf("%d %d\n",chosen.row+1, chosen.col+1);
        }

        scan.close();
    }

    public static void main(String[] args){
        new Matrix().solve();
    }
}

Back to Home

No comments:

Post a Comment