AOJ : 2218 - K Poker

問題概要

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=2218
少し変わったポーカー(K Poker)において, 自分が持っている手札5枚の点数を出力する問題です.

アルゴリズム

ひたすらWikipediaのルールにしたがって書くだけです.
よく使いそうな関数にひとまとめにして, 手間を減らすといいでしょう.

プログラム

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

#define REP(i,n,m) for(int i=n;i<m;i++)
#define rep(i,n) REP(i,0,n)

class P{
public:
  int x,y;
  P(int _x,int _y){
    x = _x;
    y = _y;
  }

  bool operator<(const P &p)const{
    return x < p.x;
  }
};

//フラッシュの判定
bool isFlash(vector<P> v){
  rep(i,v.size()-1) if(v[i].y != v[i+1].y) return false;
  return true;
}

//vectorの [n]〜[m-1] の範囲が同じランクであるかの判定
bool isSame(vector<P> v,int n,int m){
  REP(i,n,m-1) if(v[i].x != v[i+1].x) return false;
  return true;
}

//ストレートの判定
bool isStraight(vector<P> v){
  int n = 0;
  int m = v.size();
  if(v[0].x==0 && v[1].x==9) n = 1;

  REP(i,n,m-1) if(v[i].x + 1 != v[i+1].x) return false;
  return true;
}

int main(void){
  int n;
  bool firstFlg = true;

  while(cin>>n){
    if(firstFlg) firstFlg = false;
    else cout<<endl;

    int t[4][13];
    rep(i,4) rep(j,13) cin>>t[i][j];

    int s[9];
    rep(i,9) cin>>s[i];

    while(n--){
      int score = 0;
      vector<P> v;

      rep(i,5){
        string s;
        cin>>s;

        int x = ('2'<=s[0] && s[0]<='9' ? s[0]-'1' :
                 s[0]=='A' ? 0 :
                 s[0]=='T' ? 9 :
                 s[0]=='J' ? 10 :
                 s[0] == 'Q' ? 11 : 12);
        int y = (s[1]=='S' ? 0 :
                 s[1] == 'C' ? 1 :
                 s[1] == 'H' ? 2 : 3);

        score += t[y][x];
        v.push_back(P(x,y));
      }

      sort(v.begin(),v.end());

      //ロイヤルストレートフラッシュ
      if(v[0].x==0 && v[1].x==9 && isStraight(v) && isFlash(v))
        score *= s[8];
      //ストレートフラッシュ
      else if(isStraight(v) && isFlash(v))
        score *= s[7];
      //フォーカード
      else if(isSame(v,0,4) || isSame(v,1,5))
        score *= s[6];
      //フルハウス
      else if( isSame(v,0,2) && isSame(v,2,5) ||
               isSame(v,0,3) && isSame(v,3,5) )
        score *= s[5];
      //フラッシュ
      else if(isFlash(v))
        score *= s[4];
      //ストレート
      else if(isStraight(v))
        score *= s[3];
      //スリーカード
      else if(isSame(v,0,3) || isSame(v,1,4) || isSame(v,2,5))
        score *= s[2];
      //ツーペア
      else if( isSame(v,0,2) && (isSame(v,2,4) || isSame(v,3,5)) ||
               isSame(v,1,3) && isSame(v,3,5) )
        score *= s[1];
      //ワンペア
      else if( isSame(v,0,2) || isSame(v,1,3) ||
               isSame(v,2,4) || isSame(v,3,5) )
        score *= s[0];
      //役なし
      else
        score = 0;

      cout<<score<<endl;
    }
  }

  return 0;
}