ZCMU—2201 Chip Play

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Let's consider the following game. We have a rectangular field n×m in size. Some squares of the field contain chips.

Each chip has an arrow painted on it. Thus, each chip on the field points in one of the following directions: up, down, left or right.

The player may choose a chip and make a move with it.

The move is the following sequence of actions. The chosen chip is marked as the current one. After that the player checks whether there are more chips in the same row (or in the same column) with the current one that are pointed by the arrow on the current chip. If there is at least one chip then the closest of them is marked as the new current chip and the former current chip is removed from the field. After that the check is repeated. This process can be repeated several times. If a new chip is not found, then the current chip is removed from the field and the player's move ends.

By the end of a move the player receives several points equal to the number of the deleted chips.

By the given initial chip arrangement determine the maximum number of points that a player can receive during one move. Also determine the number of such moves.

Input

The first line contains two integers n and m (1≤n,m,n×m≤5000). Then follow n lines containing m characters each − that is the game field description. "." means that this square is empty. "L", "R", "U", "D" mean that this square contains a chip and an arrow on it says left, right, up or down correspondingly.

It is guaranteed that a field has at least one chip.

Output

Print two numbers − the maximal number of points a player can get after a move and the number of moves that allow receiving this maximum number of points.

Examples

Input

4 4
DRLD
U.UL
.UUR
RDDL

Output

10 1

Input

3 5
.D...
RRRLL
.U...

Output

6 2

Note

In the first sample the maximum number of points is earned by the chip in the position (3,3). You can see its progress at the following picture:

All other chips earn fewer points.

 

【分析】

題意:給出一張圖,有空白點以及方向UDLR,表示上下左右,到達當前點如果是方向,那麼就按照方向繼續走向下一格,跳過中間所有的空白格,若當前方向只剩下空白格,那麼就結束,問從任意起點出發,能走的最多步數是多少,並且有多少種方案

 

這種代碼首先考慮爆搜,dfs,bfs都可以因爲每次搜索一個點只會經過一次,所以複雜度是O(5000),那麼起點也是5000個

所以複雜度粗略估計是O(5000*5000),但是交上去會T...

P.S.當然在我們學校OJ是不會T的。。數據放小了...

但是這裏顯然還有一個複雜度沒有計算,雖然理論上是每個點只經過一次,但是在真正搜索的時候,要從(x,y)向某個方向dir搜索下一個方向塊的時候,還是會經過中間所有空白點的,所以複雜度還存在一個√500 

所以真實的複雜度應該是5000*5000*70,所以纔會超時......那麼顯然這個搜索中5000*5000是必須要存在的複雜度,那麼我們優化掉這個70就可以了

那也很簡單,這個70的存在只是因爲每次從(x,y)向某個方向尋找下一個塊的時候會經過空白塊,所以我們不再經過空白塊就可以了,把找下一塊的複雜度優化到1即可,顯然這件事情鏈表就可以解決...那麼在一張二維圖上我們需要四個方向的鏈表..也就是十字鏈表了...當然同時因爲這張圖是n*m<=5000 ,而不是5000*5000,所以建一張5000*5000的鏈表顯然是沒有意義的...hash一下就可以了

【代碼】

#include<bits/stdc++.h>
using namespace std;
 
char s[5010][5010];
int U[5050],D[5050],L[5050],R[5050];
int n,m;
 
void init(){
    for (int i = 0 ; i < n ; ++i){
        int l = -1;
        for (int j = 0 ; j < m ; ++j)
            if (s[i][j] != '.'){
                int now = i * m + j;
                L[now] = l; //l表示上一個節點的位置,上一個節點就是這個節點的左結點 
                if (l != -1) R[l] = now; //上一個節點的右節點就是這個節點的右節點 
                l = now; //記錄當前的節點狀態。 
            } 
        R[l] = -1; //每一行的最後一個節點的右節點是-1 
    }
    //分開處理 上下方向的鏈表和左右方向的鏈表 
    for (int i = 0 ; i < m ; ++i){  //同上 
        int l = -1;
        for (int j = 0 ; j < n ; ++j)
            if (s[j][i] != '.'){
                int now = j * m + i; 
                U[now] = l;
                if (l != -1) D[l] = now;
                l = now;
            }
        D[l] = -1;
    }
}
 
int dfs(int x,int y){
    int now = x * m + y;
    //到達當前節點(x,y) 首先處理十字鏈表,把當前節點刪除 
    if (U[now] != -1) D[U[now]] = D[now];  //如果這個點a上面還存在節點b,那麼節點b向下的鏈表指向應該跳過a,指向a下面的點 
    if (D[now] != -1) U[D[now]] = U[now];  //如果這個點a下面還存在節點b,那麼節點b向上的鏈表指向應該跳過a,指向a上面的點 
    if (L[now] != -1) R[L[now]] = R[now];  //如果這個點a左邊還存在節點b,那麼節點b右邊的鏈表指向應該跳過a,指向a右邊的點 
    if (R[now] != -1) L[R[now]] = L[now];  //如果這個點a右邊還存在節點b,那麼節點b左邊的鏈表指向應該跳過a,指向a左邊的點 
    
	//刪除當前點(x,y)後,向當前點的方向下一格繼續搜索 
	int go;
    if (s[x][y] == 'U') go = U[now];
    else if (s[x][y] == 'D') go = D[now];
    else if (s[x][y] == 'L') go = L[now];
    else if (s[x][y] == 'R') go = R[now];
    if (go == -1) return 1;
    return dfs(go/m,go%m) + 1;
}
 
int main() 
{
    int ans = -1, num = 0;
    scanf("%d%d",&n,&m);
    for (int i = 0 ; i < n ; ++i) scanf("%s",s[i]);
    for (int i = 0 ; i < n ; ++i)
        for (int j = 0 ; j < m ; ++j)
            if (s[i][j] != '.'){   // 遍歷所有方向塊,作爲起點搜索一遍整張圖 
                init();  // 初始化鏈表 
                int now = dfs(i,j);
                if (now > ans) ans = now,num = 1;
                else if (now == ans) ++num;
            }
    printf("%d %d\n",ans,num);
    return 0;
}

 

 

因爲數據放水了

所以下面這個簡單的dfs爆搜也可以過

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5005;
char s[maxn][maxn];
bool a[maxn][maxn];
int n,m,tmp;
int dx[] = { -1,0,1,0 };
int dy[] = { 0,1,0,-1 };
int bin( char a )
{
    if( a=='U' ) return 0;
    if( a=='R' ) return 1;
    if( a=='D' ) return 2;
    return 3;
}
int check( int x,int y )
{
    if( x>=n||x<0 ) return 0;
    if( y>=m||y<0 ) return 0;
    return 1;
}
void dfs( int x, int y ,int up)
{
    if( s[x][y]!='.'&&a[x][y]==false )
    {
        tmp++; a[x][y] = true;
        int to = bin( s[x][y] );
        int xx = x+dx[to];
        int yy = y+dy[to];
        if( check( xx,yy ) ) dfs( xx,yy,to );
    }
    else
    {
        int xx = x+dx[up];
        int yy = y+dy[up];
        if( check( xx,yy ) )
            dfs( xx,yy,up );
    }
}
int main()
{
    while( scanf( "%d%d", &n, &m )==2 )
    {
        for( int i=0;i<n;i++ )
            scanf( "%s", s[i] );
        int ans = 0, cnt = 0;
        for( int i=0;i<n;i++ )
            for( int j=0;j<m;j++ )
            if( s[i][j]!='.' )
            {
                memset( a, false, sizeof(a) );
                tmp = 0;
                dfs( i,j,bin( s[i][j] ) );
                if( ans<tmp )
                {
                    ans = tmp; cnt = 1;
                }
                else if( ans==tmp )
                {
                    cnt++;
                }
               // printf( "%d %d\n", ans ,cnt );
            }
        printf( "%d %d\n", ans ,cnt );
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章