Its rainning man!

本文介绍了一个扑克牌游戏的解决方案,通过分析不同颜色的牌来确定游戏是否可以进行。该方案考虑了从两种颜色到四种颜色的情况,并针对每种情况提出了具体的解决办法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


/**
 * CTU Open 2016
 * Problem Solution: It's Raining
 * 
 * Case analysis. Main (but not the only) approach is to play 
 * colors one by one.
 * @author Josef Cibulka
 */

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <functional>

using namespace std;

static const string colorList { "SDHC" };
static const string rankList { "23456789XJQKA" };
static const int rankCnt { 13 };

vector<vector<int> > rows;
vector<vector<int> > pairCnt;
vector<int> tripleCnt;
int quadCnt;

struct VectorComparer
{
  bool operator ()(const vector<int>& a, const vector<int>& b) const
  {
    return a.size() > b.size();
  }
};

  template <typename T>
bool vectorContains(const vector<T> &vec, T item)
{
  return (std::find(vec.begin(), vec.end(), item) != vec.end());
}

/** Exactly two card colors are present (they are colors 0 and 1). 
 * Solution exists iff there is at least one pair on these two colors. */
bool check2Colors()
{
  return (pairCnt[0][1] >=1);
}

/** Exactly three card colors are present (0, 1 and 2). 
 * Solution exists iff either:
 * a) "Path": two distinct pairs of colors, or one pair and a triple or two triples.
 * b) "Jump": row 2 has only one element and this element is part of a triple. */
bool check3Colors()
{
  int pairCntCnt = (pairCnt[0][1]>=1) + (pairCnt[0][2]>=1) + (pairCnt[1][2]>=1);
  if(pairCntCnt + tripleCnt[3] >= 2) // path
    return true;
  if(rows[2].size() == 1 && tripleCnt[3] >= 1) // jump
    return true;
  return false;
}

bool check4ColorsPath()
{   
  int pairCntCnt = 0;
  int pairCntSum = 0;
  for(int a=0; a<4; ++a)
    for(int b=a+1; b<4; ++b)
      if(pairCnt[a][b]>=1)
      {
        pairCntCnt++;
        pairCntSum += pairCnt[a][b];
      }
  int tripleCntSum = 0;
  for(int a=0; a<4; ++a)
    tripleCntSum += tripleCnt[a];

  if(quadCnt>=1)
    return (quadCnt + tripleCntSum + pairCntCnt >= 2);

  if(tripleCntSum >= 1)
    return (tripleCntSum + pairCntCnt >= 3);

  // Star centered in a.
  for(int a=0; a<4; ++a) 
  {
    bool isStar = true;
    for(int b=0; b<4; ++b) 
      for(int c=b+1; c<4; ++c)
        if(b!=a && c!=a && pairCnt[b][c] >= 1)
          isStar = false;
    // Since the star covers all 4 colors, solution exists iff at least one edge of the star is at least double.
    if(isStar)
      return (pairCntSum >= 4); 
  }
  return (pairCntCnt >= 3); // Three edges not forming a star and covering all colors => path.
}

bool check4ColorsRowWith1()
{
  int pairCntCnt = 0;
  for(int a=0; a<4; ++a)
    for(int b=a+1; b<4; ++b)
      if(pairCnt[a][b]>=1)
        pairCntCnt++;
  int tripleCntCnt = 0;
  for(int a=0; a<4; ++a)
    if(tripleCnt[a]>=1)
      tripleCntCnt++;
  if(quadCnt >= 1)
  {
    if(rows[2].size() == 1)
      return true;
    return (pairCntCnt + tripleCntCnt >= 1);
  }
  if(tripleCnt[0] + tripleCnt[1] + tripleCnt[2] >= 1) // A triple covering the single card in row 3.
    return true;
  if(rows[2].size() == 1 && tripleCntCnt >= 1) // Observe that the triple covers the single card in row 2.
    return true;
  return false;
}

bool check4ColorsRowWith2()
{ 
  for(int row2=0; row2<4; ++row2)
  {
    int tripleCntCnt = 0;
    if(rows[row2].size() != 2)
      continue;
    for(int a=0; a<4; ++a)
      if(a!=row2 && tripleCnt[a]>=1)
        tripleCntCnt++;
    if(tripleCntCnt>=2)
      return true; // Two distinct triples cover the two cards.
  }
  return false;
}



bool check4Colors()
{
  vector<bool> covered (4, false);
  for(int a=0; a<4; ++a)
    for(int b=a+1; b<4; ++b)
      if(pairCnt[a][b]>=1)
        covered[a]=covered[b]=true;
  for(int a=0; a<4; ++a)
    if(tripleCnt[a] >= 1)
      for(int i=0; i<4; ++i)
        if(i!=a)
          covered[i] = true;
  if(quadCnt>=1)
    for(int i=0; i<4; ++i)
      covered[i] = true;

  bool allCovered = !vectorContains(covered, false);
  if(!allCovered)
    return false;

  if(rows[3].size() == 1)
    if(check4ColorsRowWith1())
      return true;
  if(rows[3].size() == 2)
    if(check4ColorsRowWith2())
      return true;
  return check4ColorsPath();  
}

int main(void)
{
  int cardCnt;
  while(cin >> cardCnt)
  {
    rows = vector<vector<int> >(4, vector<int>());
    pairCnt = vector<vector<int> >(4, vector<int>(4, 0));
    tripleCnt = vector<int>(4, 0);
    quadCnt = 0;
    for(int i=0; i<cardCnt; ++i)
    {
      string card;
      cin >> card;
      int rank = rankList.find(card[0]);
      int color = colorList.find(card[1]);
      rows[color].push_back(rank);
    } 
    sort(rows.begin(), rows.end(), VectorComparer());
    /*cout << endl;
      for(auto &row : rows)
      if(row.size() > 0)      
      {
      for(int i : row)
      cout << i << " ";
      cout << endl;
      }*/

    for(int i=0; i<rankCnt; i++)
    {
      auto contFunction = bind(vectorContains<int>, placeholders::_1, i);
      int rankCardCnt = count_if(rows.begin(), rows.end(), contFunction);
      //      cout << "ranks cnt: " << rankCardCnt << endl;
      for(int a=0; a<4; ++a)
        for(int b=a+1; b<4; ++b)
        {
          if(vectorContains(rows[a], i) &&
              vectorContains(rows[b], i))
          {
            if(rankCardCnt == 2)
            {
              pairCnt[a][b]++;
              pairCnt[b][a]++;
            }
            for(int c=b+1; c<4; ++c)
            {
              if(vectorContains(rows[c], i))
              {
                if(rankCardCnt == 3)
                  tripleCnt[6-a-b-c]++;
                if(c==2 && vectorContains(rows[3], i))
                  quadCnt++;
              }
            }
          }
        }
    }

    /*cout << "Pairs:" << endl;
      for(int a=0; a<3; ++a)
      {
      for(int b=a+1; b<4; ++b)
      cout << pairCnt[a][b] << ", ";
      cout << endl;
      }
      cout << "Triples:" << endl;
      for(int a=0; a<4; ++a)
      cout << tripleCnt[a] << ", ";
      cout << endl;
      cout << "Quadruples: " << quadCnt << endl;*/

    bool result = false;
    if(rows[1].size() == 0)
      result = true;
    else if(rows[2].size() == 0)
      result = check2Colors();
    else if(rows[3].size() == 0)
      result = check3Colors();
    else
      result = check4Colors();
    cout << (result ? "YES" : "NO") << endl;
  }
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值