O(M^2)で行う上がり抽出のプログラム

pdf版:include

以下テキスト版

#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
//面子のチェック
bool check_mentsu(int NUM, vector<int> &TEHAI, int MAISU){
 if(MAISU == 0) return true;
 for(int i=0;i<NUM;i++){
  if(TEHAI[i] > 2){
  vector<int> newTEHAI(TEHAI);
  newTEHAI[i] = newTEHAI[i] - 3;
  if(check_mentsu(NUM, newTEHAI, MAISU - 3)) return true;
 }
 if(i+2 < NUM && TEHAI[i] > 0 && TEHAI[i+1] > 0 && TEHAI[i+2] > 0){
 vector<int> newTEHAI(TEHAI);
 for (int j = 0; j < 3; j++) newTEHAI[i + j]--;
 if(check_mentsu(NUM, newTEHAI, MAISU - 3)) return true;
 }
 }
return false;
 }
 //手直し版
 bool check_mentsu2(int NUM, vector<int> &TEHAI, int MAISU){
 vector<int> newTEHAI(TEHAI);
 for(int i = 0; i < NUM; i++){
 int amari = newTEHAI[i] % 3;
 MAISU = MAISU - newTEHAI[i] + amari;
 newTEHAI[i] = amari;
 if(amari != 0 && TEHAI[i+1] >= amari && TEHAI[i+2] >= amari){
 for(int j = 0; j < 3; j++)
 newTEHAI[i+j] = newTEHAI[i+j] - amari;
 MAISU = MAISU - (amari * 3);
 }
 else if(TEHAI[i+1] < amari || TEHAI[i+2] < amari)
 return false;
 }
 if(MAISU == 0) return true;
 else return false;
 }
//雀頭のチェック
 bool check_atama(int NUM, vector<int>& TEHAI, int MAISU){
 for(int i=0;i<NUM;i++){
 if(TEHAI[i] > 1){
 vector<int> newTEHAI(TEHAI);
 newTEHAI[i] = newTEHAI[i] - 2;
 if (check_mentsu2(NUM, newTEHAI, MAISU - 2)) return true;
 }
 }
 return false;
 }
//上がれるかどうかのチェック
 bool check_agari(){
 int num; //持っている牌の種類数
 //牌の種類数の入力
 //0が入力されたらプログラムを終える
 if (cin >> num && num < 1){
 return false;
 }
 vector<int> tehai(num); //持っている牌を格納するためのvector
 int maisu = 0;
 for (int i = 0; i < num; i++) {
 cin >> tehai[i];
 maisu += tehai[i];
 }
 std::cout << (check_atama(num, tehai, maisu) ? "Yes" : "No") << std::endl;
 return true;
 }
int main(){
 while (check_agari());
 return 0;
 }