110208 Yahtzee


#include <memory.h>
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>

using namespace std;

class Calculator
{
public:
	Calculator()
	{
		m_diceInTotalRounds.push_back(NULL);
	}

	~Calculator()
	{
		for (size_t i = 1; i < m_diceInTotalRounds.size(); ++i)
			delete m_diceInTotalRounds[i];
	}

	void OutputResult()
	{
		int sum = 0, award = 0;
		for (int i = 1; i <= AWARD_FUNC_CNT; ++i)
		{
			cout << m_result[i] << ' ';
			sum += m_result[i];
		}

		if (sum >= AWARD_THRESHOLD)
			award = AWARD_SCORE;
		sum += award;

		for (int i = AWARD_FUNC_CNT + 1; i <= CALC_FUNC_CNT; ++i)
		{
			cout << m_result[i] << ' ';
			sum += m_result[i];
		}

		cout << award << ' ' << sum << endl;
	}

	bool Init()
	{
		static int dice[DICE_CNT];
		for (int i = 1; i <= CALC_FUNC_CNT; ++i)
		{
			for (int j = 0; j < DICE_CNT; ++j)
			{
				if (!(cin >> dice[j]))
					return false;
			}
			AddToDiceInTotalRounds(dice);
		}

		return true;
	}

	void Calculate()
	{
		CalcInit();
		GetMaxScore(CALC_FUNC_CNT, s_calculatedRounds);
		SetResult();
	}

	static const int CALC_FUNC_CNT = 13;
	static const int DICE_CNT = 5;

private:
	int GetIndexOfToCalculatedRounds(bool* calculatedRounds)
	{
		int sum = 0, multiplyer = 1;
		for (int i = 1; i <= CALC_FUNC_CNT; ++i, multiplyer <<= 1)
		{
			if (!calculatedRounds[i])
				sum += multiplyer;
		}
		return sum;
	}

	int GetAppliedRoundOfMaxScore(int calcFunc, bool* calculatedRounds)
	{
		return s_TotalRoundsDiceScoreInfo[calcFunc][GetIndexOfToCalculatedRounds(calculatedRounds)].m_appliedRound;
	}

	void SetResult()
	{
		memset(s_calculatedRounds, 0, sizeof(s_calculatedRounds));
		for (int i = CALC_FUNC_CNT; i >= 1; --i)
		{
			int selectedRound = GetAppliedRoundOfMaxScore(i, s_calculatedRounds);
			s_calculatedRounds[selectedRound] = true;
			m_result[i] = s_SingleRoundDiceScore[i][selectedRound];
		}
	}

	void CalcInit()
	{
		InitSingleRoundDiceScore();
		InitTotalRoundsDiceScore();
		memset(s_calculatedRounds, 0, sizeof(s_calculatedRounds));
	}

	int GetMaxScore(int curCalcFunc, bool* calculatedRounds)
	{
		int index = GetIndexOfToCalculatedRounds(calculatedRounds);
		int existingMax = s_TotalRoundsDiceScoreInfo[curCalcFunc][index].m_maxScore;
		if (existingMax >= 0)
			return existingMax;

		int max = -1, selectedRound = 0;
		for (int i = 1; i <= CALC_FUNC_CNT; ++i)
		{
			if (calculatedRounds[i])
				continue;

			int curResult;
			if (curCalcFunc == 1)
				curResult = s_SingleRoundDiceScore[curCalcFunc][i];
			else
			{
				calculatedRounds[i] = true;
				curResult = s_SingleRoundDiceScore[curCalcFunc][i] + GetMaxScore(curCalcFunc - 1, calculatedRounds);
				calculatedRounds[i] = false;
			}

			if (curResult > max)
			{
				max = curResult;
				selectedRound = i;
			}
		}

		if ((curCalcFunc == AWARD_FUNC_CNT) && (max >= AWARD_THRESHOLD))
			max += AWARD_SCORE;

		s_TotalRoundsDiceScoreInfo[curCalcFunc][index].m_maxScore = max;
		s_TotalRoundsDiceScoreInfo[curCalcFunc][index].m_appliedRound = selectedRound;
		return max;
	}

	void InitTotalRoundsDiceScore()
	{
		memset(s_TotalRoundsDiceScoreInfo, 0xFF /*-1*/, sizeof(s_TotalRoundsDiceScoreInfo));
	}

	void InitSingleRoundDiceScore()
	{
		for (int i = 1; i <= CALC_FUNC_CNT; ++i)
		{
			for (int j = 1; j <= CALC_FUNC_CNT; ++j)
				s_SingleRoundDiceScore[i][j] = s_CalcFuncs[i](*(m_diceInTotalRounds[j]));
		}
	}

	void AddToDiceInTotalRounds(int* dice)
	{
		m_diceInTotalRounds.push_back(new SortedDiceInRound());
		int cnt = m_diceInTotalRounds.size();

		for (int i = 0; i < DICE_CNT; ++i)
			m_diceInTotalRounds[cnt - 1]->push_back(dice[i]);

		sort(m_diceInTotalRounds[cnt - 1]->begin(), m_diceInTotalRounds[cnt - 1]->end());
	}

	typedef vector<int> SortedDiceInRound;

	// Calculation Functions Begin
	template <int N>
	static int Count(const SortedDiceInRound& sortedDiceInRound)
	{
		int sum = 0;
		for (int i = 0; i < DICE_CNT; ++i)
		{
			if (sortedDiceInRound[i] == N)
				sum += N;
			else if (sortedDiceInRound[i] > N)
				break;
		}

		return sum;
	}

	static int Sum(const SortedDiceInRound& sortedDiceInRound)
	{
		int sum = 0;
		for (int i = 0; i < DICE_CNT; ++i)
			sum += sortedDiceInRound[i];

		return sum;
	}

	static int Same3(const SortedDiceInRound& sortedDiceInRound)
	{
		if ((sortedDiceInRound[0] == sortedDiceInRound[2]) ||
			(sortedDiceInRound[1] == sortedDiceInRound[3]) ||
			(sortedDiceInRound[2] == sortedDiceInRound[4]))
			return Sum(sortedDiceInRound);

		return 0;
	}

	static int Same4(const SortedDiceInRound& sortedDiceInRound)
	{
		if ((sortedDiceInRound[0] == sortedDiceInRound[3]) ||
			(sortedDiceInRound[1] == sortedDiceInRound[4]))
			return Sum(sortedDiceInRound);

		return 0;
	}

	static int Same5(const SortedDiceInRound& sortedDiceInRound)
	{
		if (sortedDiceInRound[0] == sortedDiceInRound[4])
			return 50;
		return 0;
	}

	static int SmallSeq(const SortedDiceInRound& sortedDiceInRound)
	{
		set<int> seqSet;
		for (int i = 0; i < DICE_CNT; ++i)
			seqSet.insert(sortedDiceInRound[i]);

		if (seqSet.size() < 4)
			return 0;

		if ((seqSet.find(3) == seqSet.end()) || (seqSet.find(4) == seqSet.end()))
			return 0;

		if ((seqSet.find(1) != seqSet.end()) && (seqSet.find(2) != seqSet.end()))
			return 25;

		if ((seqSet.find(2) != seqSet.end()) && (seqSet.find(5) != seqSet.end()))
			return 25;

		if ((seqSet.find(5) != seqSet.end()) && (seqSet.find(6) != seqSet.end()))
			return 25;

		return 0;
	}

	static int BigSeq(const SortedDiceInRound& sortedDiceInRound)
	{
		if ((sortedDiceInRound[0] == 1) && 
			(sortedDiceInRound[4] == 5) && 
			(sortedDiceInRound[1] == 2) && 
			(sortedDiceInRound[2] == 3) && 
			(sortedDiceInRound[3] == 4))
			return 35;
		if ((sortedDiceInRound[0] == 2) && 
			(sortedDiceInRound[4] == 6) && 
			(sortedDiceInRound[1] == 3) && 
			(sortedDiceInRound[2] == 4) && 
			(sortedDiceInRound[3] == 5))
			return 35;
		return 0;
	}

	static int Calabash(const SortedDiceInRound& sortedDiceInRound)
	{
		if ((sortedDiceInRound[0] == sortedDiceInRound[2]) && (sortedDiceInRound[3] == sortedDiceInRound[4]))
			return 40;
		if ((sortedDiceInRound[2] == sortedDiceInRound[4]) && (sortedDiceInRound[0] == sortedDiceInRound[1]))
			return 40;
		return 0;
	}
	// Calculation Functions End

private:
	static const int DIM_CNT = ((1 << CALC_FUNC_CNT) - 1);
	static const int AWARD_FUNC_CNT = 6;
	static const int AWARD_THRESHOLD = 63;
	static const int AWARD_SCORE = 35;
	static bool s_calculatedRounds[CALC_FUNC_CNT + 1];

	typedef int (*PCALC_FUNC)(const SortedDiceInRound& sortedDiceInRound);
	const static PCALC_FUNC s_CalcFuncs[CALC_FUNC_CNT + 1];

	/* Structure of s_SingleRoundDiceScore
	Methods     | Round1 | Round2 | ... | Round13 |
	-----------------------------------------------
	Method1     |   x1,1 |   x1,2 | ... |   x1,13 |
	Method2     |   x1,1 |   x1,2 | ... |   x1,13 |
	...         |   ...  |   ...  | ... |   ...   |
	Method13    |  x13,1 |  x13,2 | ... |  x13,13 |
	*/
	static int s_SingleRoundDiceScore[CALC_FUNC_CNT + 1][CALC_FUNC_CNT + 1]; 

	struct ScoreInfo
	{
		int m_maxScore;
		int m_appliedRound;
	};
	static ScoreInfo s_TotalRoundsDiceScoreInfo[CALC_FUNC_CNT + 1][DIM_CNT + 1];

	vector<SortedDiceInRound*> m_diceInTotalRounds;

	int m_result[CALC_FUNC_CNT + 1]; // Store the score for each calculation function.
};

int Calculator::s_SingleRoundDiceScore[CALC_FUNC_CNT + 1][CALC_FUNC_CNT + 1];
Calculator::ScoreInfo Calculator::s_TotalRoundsDiceScoreInfo[CALC_FUNC_CNT + 1][DIM_CNT + 1];
bool Calculator::s_calculatedRounds[Calculator::CALC_FUNC_CNT + 1];
const Calculator::PCALC_FUNC Calculator::s_CalcFuncs[] = {
	NULL,
	Calculator::Count<1>,
	Calculator::Count<2>,
	Calculator::Count<3>,
	Calculator::Count<4>,
	Calculator::Count<5>,
	Calculator::Count<6>,
	Calculator::Sum,
	Calculator::Same3,
	Calculator::Same4,
	Calculator::Same5,
	Calculator::SmallSeq,
	Calculator::BigSeq,
	Calculator::Calabash
};

void DoTest()
{
	while(true)
	{
		Calculator calc;
		if (!calc.Init())
			return;
		calc.Calculate();
		calc.OutputResult();
	}
}

int main(int argc, char* argv[])
{
	DoTest();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值