首页 > 代码库 > Hackerrank - Coin on the Table 题解

Hackerrank - Coin on the Table 题解

这回又是忽略了题目中的一句话:When the coin reaches the cell that has letter ‘*’ it will be there permanently. 

就是说当走到这个格子的时候,就可以定住在这个格子的了。不过这个时候也可以从别的方向走过来,所以题目的真正意思是,在k步内走到这个格子使用的最小的修改指令是多少,并不一定需要就在第k步到达这个格子。

思路:

使用动态规划法,记录1到k步可以到达的格子,然后从中选择出最小的修改指令数,就是答案了。

原题请看:https://www.hackerrank.com/challenges/coin-on-the-table


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

class CoinontheTable
{
	int n, m, steps;
	const static int MAX_M = 52*52;

	inline int fourMin(int a, int b, int c, int d)
	{
		return min(a, min(b, min(c, d)));
	}

	void fillTbl(vector<vector<vector<int> > > &tbl, vector<string> &vs,
		int i, int r, int c)
	{
		if (r + c > i || i % 2 != (r+c) %2)
		{
			tbl[r][c][i] = -1;
			return;
		}
		int down=MAX_M, up=MAX_M, left=MAX_M, right=MAX_M;
		if (r > 0 && -1 != tbl[r-1][c][i-1] && vs[r-1][c] != ‘*‘)
		{
			down = tbl[r-1][c][i-1];
			if (vs[r-1][c] != ‘D‘) down++;
		}
		if (c > 0 && -1 != tbl[r][c-1][i-1] && vs[r][c-1] != ‘*‘)
		{
			left = tbl[r][c-1][i-1];
			if (vs[r][c-1] != ‘R‘) left++;
		}
		if (r+1 < n && -1 != tbl[r+1][c][i-1] && vs[r+1][c] != ‘*‘)
		{
			up = tbl[r+1][c][i-1];
			if (vs[r+1][c] != ‘U‘) up++;
		}
		if (c+1 < m && -1 != tbl[r][c+1][i-1] && vs[r][c+1] != ‘*‘)
		{
			right = tbl[r][c+1][i-1];
			if (vs[r][c+1] != ‘L‘) right++;
		}
		tbl[r][c][i] = fourMin(left, right, up, down);
		if (MAX_M == tbl[r][c][i]) tbl[r][c][i] = -1;
	}
public:
	CoinontheTable()
	{		
		cin>>n>>m>>steps;
		vector<string> vs(n);
		for (int i = 0; i < n; i++)
		{
			cin>>vs[i];
		}
		vector<vector<vector<int> > >
			tbl(n, vector<vector<int> >(m, vector<int>(steps+1, -1)));
		if (0 == m || 0 == n || steps < 0)
		{
			cout<<-1;
			return;
		}
		tbl[0][0][0] = 0;
		for (int i = 1; i <= steps; i++)
		{
			for (int r = 0; r <= i && r < n; r++)
			{
				for (int c = 0; c <= i && c < m; c++)
				{
					fillTbl(tbl, vs, i, r, c);
				}
			}
		}
		int ans = MAX_M;
		for (int r = 0; r < n; r++)
		{
			for (int c = 0; c < m; c++)
			{
				if (‘*‘ == vs[r][c])
				{
					for (int i = 0; i <= steps; i++)
					{
						if (-1 != tbl[r][c][i])
							ans = min(ans, tbl[r][c][i]);
					}
					break;
				}
			}
		}
		if (MAX_M == ans) cout<<-1;
		else cout<<ans;
	}
};
/*
When the coin reaches the cell that has letter ‘*’ it will be there permanently.
*/

int main()
{
	CoinontheTable();
	return 0;
}