Official

B - Mongeness Editorial by leaf1415


与えられたマス目が問題文の条件を満たすかどうかを実際に確認することで、この問題を解くことができます。 つまり、\(1 \leq i_1 < i_2 \leq H\) および \(1 \leq j_1 < j_2 \leq W\) を満たすすべての整数の組 \((i_1, i_2, j_1, j_2)\) について、\(A_{i_1, j_1} + A_{i_2, j_2} \leq A_{i_2, j_1} + A_{i_1, j_2}\) が成り立つかどうかを実際に確認します。

ある整数の組 \((i_1, i_2, j_1, j_2)\)\(A_{i_1, j_1} + A_{i_2, j_2} \leq A_{i_2, j_1} + A_{i_1, j_2}\) を満たすかどうかの判定にはプログラミング言語の条件分岐の機能を用いることができます(例えば C++言語では if 文がこれを実現します)。 また、この判定を対象となる整数の組のすべてに対して行うためには、プログラミング言語の繰り返しの機能を用いることができます(例えば C++言語では for 文がこれを実現します)。

この解法の時間計算量は \(\mathrm{O}(N^4)\) です。

以下に、C++言語による実装例を記載します。

#include <iostream>
using namespace std;

int main(void)
{
  int h, w;
  int a[51][51];

  cin >> h >> w;
  for(int i = 1; i <= h; i++){
    for(int j = 1; j <= w; j++){
      cin >> a[i][j];
    }
  }

  for(int i_1 = 1; i_1 <= h; i_1++){
    for(int i_2 = i_1+1; i_2 <= h; i_2++){
      for(int j_1 = 1; j_1 <= w; j_1++){
        for(int j_2 = j_1+1; j_2 <= w; j_2++){
          if(a[i_1][j_1] + a[i_2][j_2] > a[i_2][j_1] + a[i_1][j_2]){
            cout << "No" << endl;
            return 0;
          }
        }
      }
    }
  }

  cout << "Yes" << endl;

  return 0;
}

問題文の条件を満たす(答えが Yes となる)行列 \(A\) は Monge 配列や Monge 行列と呼ばれ、\(A\) が Monge 行列であることは下記の条件と同値であることが知られていいます。

\(1 \leq i \leq H-1\) および \(1 \leq j \leq W-1\) を満たすすべての整数の組 \((i, j)\) について、\(A_{i, j} + A_{i+1, j+1} \leq A_{i+1, j} + A_{i, j+1}\) が成り立つ。

したがって、与えられたマス目が上記の条件を満たすかどうかを判定することで、\(\mathrm{O}(N^2)\) 時間でこの問題を解くこともできます。

posted:
last update: