hrbust/哈理工oj 1042 过河卒【记忆化搜索】

过河卒

Time Limit: 5000 MS

Memory Limit: 65536 K

 

Total Submit: 162(35 users)

Total Accepted: 34(22 users)

Rating: 

Special Judge: No

 

Description

Lda学会了中国象棋,在一次与Kevin的切磋中,Lda不幸只剩下一只过河卒了,而Kevin还有很多棋子。

 

过河卒在棋盘上能移动的范围是一个5×9的平面(如图)。据Kevin介绍,过河卒每一步都可以选择向前、左、或右移一格,但是不能后退,也不能移出棋盘边界。途中如果经过敌人的棋子,那么敌人的棋子就被吃掉了。

考虑到Lda初学,为了能让游戏不至于过快结束,Kevin决定让Lda的过河卒连走k步,在这k步中Kevin不走棋。Lda希望在这k步中他能吃掉尽可能多的棋子,请问他最多能吃掉Kevin多少棋子呢?

Input

第一行一个正整数T,表示测试数据的组数。接下来每组数据第一行一个正整数k (k ≤ 100),表示Lda可以连续走棋的步数。然后接下来的5行表示棋盘状态,每行一个9个字符的字符串,其中’*’表示没有棋子,’K’表示有Kevin的棋子,’L’表示这里是Lda的过河卒的初始位置(棋盘上有且只有一个’L’)

Output

每组数据输出一行,表示Lda最多能吃掉的棋子数。

Sample Input

3

5

**KKK****

****K****

**K*K**K*

KK****L**

**K******

9

*********

**K******

*********

**K****K*

******L**

8

*********

**K******

*********

**K****K*

******L**

Sample Output

3

3

2

 

分析:首先,对于这个题来讲,因为有很多格子有可能会重复走的情况,所以我们第一个要处理的问题就是判重问题,辣么如何判重呢?第一反应是状压, 但是K因为比较多,这种方法还是行不通的,那如果一路特判各种if、else估计应该可以,但是还是比较复杂,这里我们采用记忆化搜索的方法来解题。


思路:


首先我们对于K的重复拿取要有相应的判断,我们可以用两个变量l、r来表示当前行走到的最左端和最右端,当然如果想拿一个K,当然这个K一定不是在l、r之间的。这样我们就能够解决了重复拿取K的问题,辣么如何搞定l、r到底放在哪里最好呢?我们干脆不要考虑,用dp的思想,能够枚举的可能都枚举出来,我们也就不需要贪心搞这一部分了,辣么不难想到dp数组我们这样设定:

dp【x】【y】【step】【l】【r】;表示的含义还是浅显易懂的。


辣么状态转移方程嘞?一共有三种走法,辣么我们控制三种走法即可:

dp【x】【y】【step】【l】【r】=max(dp【x-1】【y】【step-1】【l】【r】(我们用a来表示),dp【x】【y-1】【step-1】【l】【r】(我们用b来表示),dp【x】【y+1】【step-1】【l】【r】(我们用c来表示));

因为涉及到l、r的变化问题,我们涉及到细节的处理:

对于a:

首先要控制x大于0

a=dp【x-1】【y】【step】【y】【y】+(map【x-1】【y】==‘K'?1:0);

对于b:

首先要控制y大于0

然后如果y大于l辣么b=dp【x】【y-1】【step】【l】【r】否则,b=dp【x】【y-1】【step】【l-1】【r】+(map【x】【y-1】==‘K'?1:0)【因为只有这种情况才不会重复拿取K】

对于c:

首先要控制y小于8(因为y+1==8,如果y==8那么y+1==9属于非法操作)

然后如果y小于r辣么c=dp【x】【y+1】【step】【l】【r】否则,c=dp【x】【y-1】【step】【l】【r+1】+(map【x】【y-1】==‘K'?1:0)

所有操作搞定完毕,最后就是代码实现部分:

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int k;
char a[15][15];
int dp[7][11][105][11][11];
int sx,sy;
int check(int x,int y)
{
    if(a[x][y]=='K')return 1;
    else return 0;
}
int dfs(int x,int y,int step,int l,int r)
{
    if(dp[x][y][step][l][r]==-1)
    {
        if(step==0)return dp[x][y][step][l][r]=0;
        int maxn=0;
        if(x>0)
        maxn=max(maxn,dfs(x-1,y,step-1,y,y)+check(x-1,y));
        if(y>0)
        {
            if(y>l)maxn=max(maxn,dfs(x,y-1,step-1,l,r));
            else maxn=max(maxn,dfs(x,y-1,step-1,l-1,r)+check(x,y-1));
        }
        if(y<8)
        {
            if(y<r)maxn=max(maxn,dfs(x,y+1,step-1,l,r));
            else maxn=max(maxn,dfs(x,y+1,step-1,l,r+1)+check(x,y+1));
        }
       // printf("%d\n",maxn);
        return dp[x][y][step][l][r]=maxn;
    }
    else return dp[x][y][step][l][r];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,-1,sizeof(dp));
        scanf("%d",&k);
        for(int i=0; i<5; i++)
        {
            scanf("%s",a[i]);
            for(int j=0; j<9; j++)
            {
                if(a[i][j]=='L')
                {
                    sx=i;
                    sy=j;
                }
            }
        }
        printf("%d\n",dfs(sx,sy,k,sy,sy));
    }
}














你可能感兴趣的:(1042,1042,hrbust,哈理工oj)