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;
        }

    }

}

    这个题开始被题目搞得有点郁闷,也就是被它的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[] = {110-1-1-101}
;
int g_OffsetY[] = {0-1-1-10111}
;

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编辑  收藏  举报

导航