yokobuttonの不定期で競技プログラミングをするブログ

不定期で解けた競技プログラミングコンテストの問題を載せています。

東京海上日動プログラミングコンテスト2022(AtCoder Beginner Contest 256)C - Filling 3x3 array

問題の要約
6個の整数、h1,h2,h3,w1,w2,w3が与えられる。
縦横3×3のマス目に、以下の条件をすべて満たすように各マスに正の整数を1つずつ書き込むことを考える。
 ・i=1,2,3について、上からi行目に書き込んだ数の和がhiになる。
 ・j=1,2,3について、左からj列目に書き込んだ数の和がwjになる。
条件を満たす書き込み方は全部で何通り存在するか?


制約
3<=h1,h2,h3,w1,w2,w3<=30


入力
h1 h2 h3 w1 w2 w3


考え方
1,3×3の行列のマスに名前をつける。
  m00 m01 m02
  m10 m11 m12
  m20 m21 m22
2,3*3で9重のfor文になりそうだが、m02,m12,m20,m21,m22はm00,m01,m10,m11が決まればh1,h2,h3,w1,w2,w3から引き算で求まるので、4重のfor文で大丈夫。


実際のプログラム
#include<iostream>
#include<vector>

using namespace std;

int main(){
  vector<int> h(3);
  vector<int> w(3);
  cin >> h[0] >> h[1] >> h[2];
  cin >> w[0] >> w[1] >> w[2];
  
  int ans = 0;
  for(int m00 = 1; m00 <= 30; ++m00){
    for(int m01 = 1; m01 <= 30; ++m01){
      int m02 = h[0] - m00 - m01;
      if(m02 <= 0){
        continue;
      }
      for(int m10 = 1; m10 <= 30; ++m10){
        int m20 = w[0] - m00 - m10;
        if(m20 <= 0){
          continue;
        }
        for(int m11 = 1; m11 <= 30; ++m11){
          int m12 = h[1] - m10 - m11;
          if(m12 <= 0){
            continue;
          }
          
          int m21 = w[1] - m01 - m11;
          if(m21 <= 0){
            continue;
          }
          
          int m22_1 = h[2] - m20 - m21;
          if(m22_1 <= 0){
            continue;
          }
          int m22_2 = w[2] - m02 - m12;
          if(m22_2 <= 0){
            continue;
          }
          
          if(m22_1 == m22_2){
            ++ans;
          }
        }
      }
    }
  }
  
  cout << ans << endl;
  
  return 0;
}