C 【NOIP2017提高組模擬12.18】

Description

給出一個H的行和W列的網格。第i行第j列的狀態是由一個字母的A[i][j]表示,如下:
“.” 此格爲空。
“o” 此格包含一個機器人。
“E” 此格包含一個出口,保證出口在整個網格中有且只有一個
每次可以選擇上,下,左,右之一的方向,將所有剩餘的機器人向這個方向移動一個格子,如果一個機器人被移出了網格,那麼這個機器人會爆炸,並立即消失。如果一個機器人移動到出口所在的格子,機器人將獲救,並消失,最多有多少機器人獲救。

Input

第一行兩個整數n,m
接下來一個n*m的字符矩陣,共n行,每行m個字符,每個字符之間無空格,字符意義如題所示。

Output

輸出一個整數,即最大的獲救的機器人的數量

Sample Input

【樣例輸入1】
3 3
o.o
.Eo
ooo
【樣例輸入2】
3 4
o…
o…
oooE

Sample Output

【樣例輸出1】
3
【樣例輸出2】
5

Data Constraint

對於20%的數據,n*m<=9
對於另外40%的數據,出口在網格圖的最左上角,即第1行第1列。
對於100%的數據,n,m<=100

Hint

移動序列爲左,上,右時,第2行第3個與第3行第2,3個機器人獲救,其他機器人爆炸


解法

dp。
我們可以知道,如果我們犧牲掉最左邊一列,那麼出口右邊的一列就能夠加入答案。那麼四個方向上的是同理。
設f[l][r][u][d]表示左邊犧牲l列,右邊r列,上面u行,下面d行能夠獲得的最大數量。轉移明顯了。

發現空間會炸,可以開滾動。
懶得人直接用小一點的數據類型
然而我因爲數組沒開夠調了兩天QwQ.


代碼

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(short i=a;i<=b;i++)

using namespace std;

const short maxn=105;
short f[maxn][maxn][maxn][maxn],H[maxn][maxn],L[maxn][maxn],map[maxn][maxn],n,m,x,y,ans;
char ch;

short max(short x,short y)
{
    if (x>y) return x; else return y;
}
short min(short x,short y)
{
    if (x<y) return y; else return x;
}
int main()
{
//  freopen("T.in","r",stdin); 
//  freopen("T.out","w",stdout);
    cin>>n>>m;
    ch=getchar();
    fo(i,1,n){
        while(ch!='o'&&ch!='.'&&ch!='E') ch=getchar();
        short j=1;
        while (ch=='o'||ch=='.'||ch=='E'){
            if (ch=='o') map[i][j]=1;
            else if (ch=='E') x=i,y=j;
            ch=getchar();
            ++j;
        }
    }
    fo(i,1,n)
        fo(j,1,m) H[i][j]=H[i][j-1]+map[i][j];
    fo(i,1,m)
        fo(j,1,n) L[i][j]=L[i][j-1]+map[j][i];
    memset(f,128,sizeof(f));
    f[0][0][0][0]=0;
    fo(l,0,m-y)
        fo(r,0,y-1)
            fo(u,0,n-x)
                fo(d,0,x-1)
                if (f[l][r][u][d]>=0)
                {
                    if (y+l+1<=m-r){
                        f[l+1][r][u][d]=max(f[l+1][r][u][d],
                            f[l][r][u][d]+L[y+l+1][min(x+u,n-d)]-L[y+l+1][max(x-d-1,u)]);
                        ans=max(ans,f[l+1][r][u][d]);
                    }

                    if (y-r-1>l){
                        f[l][r+1][u][d]=max(f[l][r+1][u][d],
                            f[l][r][u][d]+L[y-r-1][min(x+u,n-d)]-L[y-r-1][max(x-d-1,u)]);
                        ans=max(ans,f[l][r+1][u][d]);
                    }   

                    if (x+u+1<=n-d){
                        f[l][r][u+1][d]=max(f[l][r][u+1][d],
                            f[l][r][u][d]+H[x+u+1][min(y+l,m-r)]-H[x+u+1][max(y-r-1,l)]);
                        ans=max(ans,f[l][r][u+1][d]);
                    }           
                    if (x-d-1>u){
                        f[l][r][u][d+1]=max(f[l][r][u][d+1],
                            f[l][r][u][d]+H[x-d-1][min(y+l,m-r)]-H[x-d-1][max(y-r-1,l)]);
                        ans=max(ans,f[l][r][u][d+1]);
                    }   
                }
    printf("%d",ans);
}

這裏寫圖片描述

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