hrbust/哈理工oj 1042 過河卒【記憶化搜尋】
過河卒 |
||||||
|
||||||
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的重複拿取要有相應的判斷,我們可以用兩個變數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));
}
}