[topcoder]ActivateGame

http://community.topcoder.com/stat?c=problem_statement&pm=10750&rd=14153

http://apps.topcoder.com/wiki/display/tc/SRM+470

因为是棋盘型,然后就想到棋盘型DP;觉得不行,就想到BFS/DFS(这时其实已经把这个看成一张图了)。发现,寻找下一个节点进来的时候,总是要全局考虑所有已经Activate的点,BFS/DFS未果。此时感觉有点像最小生成树的Prim算法,用贪心的,但不知如何证明。此时看了一下题解,发现果然可以规约成最小生成树。因为本质是把棋盘看成一棵树后,整个过程就是Prim的过程。Kruskal的复杂度是O(e*loge),适合求稀疏的图,Prim的复杂度是O(n*n),与边无关,适合求稠密的图。(注:Prim使用堆优化效率可更高。)

Prim算法的讲解:http://www.nocow.cn/index.php/Prim%E7%AE%97%E6%B3%95

参考答案的实现也是O(n*n)的,n为w*h。虽然实现方法和纯粹用邻接表表示的有不同(因为具体问题),但效率并无退化。

我在实现错误的将四个方向的组合从(1,0)这样的搞成了(1,-1)。这表示用两个数组,然后循环遍历,也很简洁。其实里面的变量可以命名为row, col等。

int[] r = new int[] {0, 1, 0, -1};

int[] v = new int[] {1, 0, -1, 0};

代码:

import java.math.*;

public class ActivateGame

{

	public int findMaxScore(String[] grid)

	{

		int h = grid.length;

		int w = grid[0].length();

		boolean[][] activated = new boolean[h][w];

		activated[0][0] = true;

		int[] r = new int[] {0, 1, 0, -1};

		int[] v = new int[] {1, 0, -1, 0};

		int sum = 0;

		for (int cnt = 1; cnt < h*w; cnt++)

		{

			int max = 0;

			int ar = 0;

			int av = 0;

			for (int i = 0; i < h; i++)

			for (int j = 0; j < w; j++)

			{

				if (activated[i][j])

				{

					for (int x = 0; x < 4; x++)

					{

						if (isValid(i+r[x], j+v[x], h, w) && !activated[i+r[x]][j+v[x]])

						{

							int score = Math.abs(getScore(grid[i].charAt(j))-

												getScore(grid[i+r[x]].charAt(j+v[x])));

							if (score > max) 

							{

								max = score;

								ar = i+r[x];

								av = j+v[x];

							}

						}

					}

				}

			}

			sum += max;

			activated[ar][av] = true;

		}

		return sum;

	}	

	private int getScore(char c)

	{

		if (c >= '0' && c <= '9')

		{

			return c - '0';

		}

		else if (c >= 'a' && c <= 'z')

		{

			return c - 'a' + 10;

		}

		else if (c >= 'A' && c <= 'Z')

		{

			return c - 'A' + 36;

		}

		return 0;

	}	

	private boolean isValid(int x, int y, int h, int w)

	{

		return (x >=0 && x< h && y>=0 && y < w);

	}

}

  

 

你可能感兴趣的:(topcoder)