Code: Google Code Jam China 2005
昨天在TopCoder上做了Google Code Jam China 2005的考题。虽然题都不是太难,毕竟才是海选哈,题目类型一个是排列组合类问题,一个是搜索类问题。不过要在1小时内调试并提交两个算法题的代码,对于我这样离开学校工作了几年的人,还是挺不容易的。结果只完成了一道题,没有了继续参加后续比赛的资格。
由于TopCoder严厉声明不能私自转载它的考题,那么我贴出我自己做的试题的答案应该没有什么问题吧?下面这是750 Points那个搜索问题的C#版代码:
namespace CodeJam
{
class Program
{
static void Main(string[] args)
{
WordPath wp = new WordPath();
System.DateTime dt = System.DateTime.Now;
string[] grid = new string[] { "ABABA", "BABAB", "ABABA", "BABAB", "ABABA" };
int count = wp.countPaths(grid, "ABABABABABABAB");
System.Console.WriteLine(count.ToString("N") + "\r\nElapsed Time: "
+ (System.DateTime.Now - dt).TotalMilliseconds);
System.Console.Read();
}
}
public class WordPath
{
public int countPaths(string[] grid, string find)
{
int pathCount=0;
for ( int i=0 ; i < grid.Length ; ++i )
{
for ( int j=0 ; j < grid.Length ; ++j )
{
if ( grid[i][j] == find[0] )
{
pathCount += GetCanGot(grid, j, i, find, 1);
}
}
}
if ( pathCount > 1000000000 )
{
return -1;
}
return pathCount;
}
public int GetCanGot(string[] strGrid, int x, int y, string find, int index)
{
int cnt = 0;
char ch = find[index];
int len = strGrid.Length;
if ( x >= 1 && strGrid[y][x-1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x-1, y, find, index+1);
}
if ( x+1 < len && strGrid[y][x+1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x+1, y, find, index+1);
}
if ( y >= 1 && strGrid[y-1][x] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x, y-1, find, index+1);
}
if ( y+1 < len && strGrid[y+1][x] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x, y+1, find, index+1);
}
if ( x >= 1 && y >= 1 && strGrid[y-1][x-1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x-1, y-1, find, index+1);
}
if ( x >= 1 && y+1 < len && strGrid[y+1][x-1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x-1, y+1, find, index+1);
}
if ( x+1 < len && y >= 1 && strGrid[y-1][x+1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x+1, y-1, find, index+1);
}
if ( x+1 < len && y+1 < len && strGrid[y+1][x+1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x+1, y+1, find, index+1);
}
return cnt;
}
}
}
{
class Program
{
static void Main(string[] args)
{
WordPath wp = new WordPath();
System.DateTime dt = System.DateTime.Now;
string[] grid = new string[] { "ABABA", "BABAB", "ABABA", "BABAB", "ABABA" };
int count = wp.countPaths(grid, "ABABABABABABAB");
System.Console.WriteLine(count.ToString("N") + "\r\nElapsed Time: "
+ (System.DateTime.Now - dt).TotalMilliseconds);
System.Console.Read();
}
}
public class WordPath
{
public int countPaths(string[] grid, string find)
{
int pathCount=0;
for ( int i=0 ; i < grid.Length ; ++i )
{
for ( int j=0 ; j < grid.Length ; ++j )
{
if ( grid[i][j] == find[0] )
{
pathCount += GetCanGot(grid, j, i, find, 1);
}
}
}
if ( pathCount > 1000000000 )
{
return -1;
}
return pathCount;
}
public int GetCanGot(string[] strGrid, int x, int y, string find, int index)
{
int cnt = 0;
char ch = find[index];
int len = strGrid.Length;
if ( x >= 1 && strGrid[y][x-1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x-1, y, find, index+1);
}
if ( x+1 < len && strGrid[y][x+1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x+1, y, find, index+1);
}
if ( y >= 1 && strGrid[y-1][x] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x, y-1, find, index+1);
}
if ( y+1 < len && strGrid[y+1][x] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x, y+1, find, index+1);
}
if ( x >= 1 && y >= 1 && strGrid[y-1][x-1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x-1, y-1, find, index+1);
}
if ( x >= 1 && y+1 < len && strGrid[y+1][x-1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x-1, y+1, find, index+1);
}
if ( x+1 < len && y >= 1 && strGrid[y-1][x+1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x+1, y-1, find, index+1);
}
if ( x+1 < len && y+1 < len && strGrid[y+1][x+1] == ch )
{
if ( index == find.Length-1 ) cnt++;
else cnt += GetCanGot(strGrid, x+1, y+1, find, index+1);
}
return cnt;
}
}
}
这个题开始被题目搞得有点郁闷,也就是被它的sample input误导了一下,它的那个4*3*3*3那个示例太迷惑人了:(。上面这个解法在google 1G个路径搜索限制下,在P4 2.4的机器上,最大需要大约40s的运行时间,这样的Performance似乎太磕碜了。
于是后来又用C++写了一遍,效率也没有什么提高,而且比C#版还略微底些:
// CodingCpp.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "string.h"
#include <windows.h>
char ** g_Grid;
char * g_Find;
size_t g_Order;
size_t g_FindLength;
int g_OffsetX[] = {1, 1, 0, -1, -1, -1, 0, 1};
int g_OffsetY[] = {0, -1, -1, -1, 0, 1, 1, 1};
int getCanGot(int curX, int curY, int index)
{
int tmpX, tmpY, cnt = 0;
for ( int k=0 ; k < 8 ; ++k )
{
tmpX = curX + g_OffsetX[k], tmpY = curY + g_OffsetY[k];
if ( tmpX >= 0 && tmpX < g_Order && tmpY >= 0 && tmpY < g_Order
&& (*(g_Grid[tmpX]+tmpY)) == *(g_Find+index) )
{
if ( index == g_FindLength-1 ) cnt++;
else cnt += getCanGot(tmpX, tmpY, index+1);
}
}
return cnt;
}
int countPaths(char * grid[], char * find)
{
g_Grid = grid;
g_Find = find;
g_Order = strlen(*grid);
g_FindLength = strlen(find);
int count = 0;
for ( size_t i=0 ; i < g_Order ; ++i )
{
for ( size_t j=0 ; j < g_Order ; ++j )
{
if ( *(grid[j]+i) == *find )
{
count += getCanGot(j, i, 1);
}
}
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
char * grid[] = {"ABABA", "BABAB", "ABABA", "BABAB", "ABABA"};
char * find = "ABABABABABABAB";
int tick = GetTickCount();
size_t count = countPaths(grid, find);
printf("%d\n", count);
printf("%d\n", GetTickCount()-tick);
getchar();
return 0;
}
#include "stdafx.h"
#include "string.h"
#include <windows.h>
char ** g_Grid;
char * g_Find;
size_t g_Order;
size_t g_FindLength;
int g_OffsetX[] = {1, 1, 0, -1, -1, -1, 0, 1};
int g_OffsetY[] = {0, -1, -1, -1, 0, 1, 1, 1};
int getCanGot(int curX, int curY, int index)
{
int tmpX, tmpY, cnt = 0;
for ( int k=0 ; k < 8 ; ++k )
{
tmpX = curX + g_OffsetX[k], tmpY = curY + g_OffsetY[k];
if ( tmpX >= 0 && tmpX < g_Order && tmpY >= 0 && tmpY < g_Order
&& (*(g_Grid[tmpX]+tmpY)) == *(g_Find+index) )
{
if ( index == g_FindLength-1 ) cnt++;
else cnt += getCanGot(tmpX, tmpY, index+1);
}
}
return cnt;
}
int countPaths(char * grid[], char * find)
{
g_Grid = grid;
g_Find = find;
g_Order = strlen(*grid);
g_FindLength = strlen(find);
int count = 0;
for ( size_t i=0 ; i < g_Order ; ++i )
{
for ( size_t j=0 ; j < g_Order ; ++j )
{
if ( *(grid[j]+i) == *find )
{
count += getCanGot(j, i, 1);
}
}
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
char * grid[] = {"ABABA", "BABAB", "ABABA", "BABAB", "ABABA"};
char * find = "ABABABABABABAB";
int tick = GetTickCount();
size_t count = countPaths(grid, find);
printf("%d\n", count);
printf("%d\n", GetTickCount()-tick);
getchar();
return 0;
}
上面代码中的示例有111,478,680个paths,C#版和C++版分别耗时:2671.875ms和4281ms。虽然代码逻辑稍有不同,不过这个差别也确实让人大跌眼镜wa。
硬件:P4 2.4G 512M
软件:WinXP SP2, VS.NET 2005
posted on 2005-12-13 22:46 birdshome 阅读(4090) 评论(16) 编辑 收藏 举报