P7660 [COCI2014-2015#5] ZMIJA 题解

思路:

对于第 i 行,如果本行的所有的苹果都吃完了,那么有以下几种情况:

  • 若本行往左走,则现在的列下标必须大于等于上一行最左边的苹果的列下标。
  • 若本行往右走,则现在的列下标必须小于等于上一行最右边的苹果的列下标。

如果满足以上任意一条,则就可以走到上一行。

if(f == 1 && y >= fr[x-1] && Sum >= J[x]) {
    if(dfs(x-1, y, 2, 1) == false)
        return false;
} else if(f == 2 && y <= fl[x-1] && Sum >= J[x]) {
    if(dfs(x-1, y, 1, 1) == false)
        return false;
}

如果一条都不满足,则该往左走往左走,该往右走往右走。

if(f == 1) {
    if(dfs(x, y+1, f, 0) == false)
        return false;
} else {    
    if(dfs(x, y-1, f, 0) == false)
        return false;
}

注意:

为了方便我们将 dfs 定义成 bool 类型,如果吃完了最后一个苹果就返回 false。

代码:

#include <bits/stdc++.h>

using namespace std;

int n, m, cnt, sum, eat, Sum;
char mp[1010][1010];
int fr[1010], fl[1010], J[1010];
//fr[i]:表示第i行最右边的J的位置 
//fl[i]:表示第i行最左边的J的位置 
//J[i]:表示第i行J的数量 

//F:是否要更新Sum
//Sum:本行出现‘J’的个数
//f:方向,1向右,2向左
//x、y:所在的行和列  
bool dfs(int x, int y, int f, int F) {
    if(F == 1)
        Sum = 0;
    if(mp[x][y] == 'J')
        eat++, Sum++;
    if(eat == sum)
        return false; 
    cnt++;
    if(f == 1 && y >= fr[x-1] && Sum >= J[x]) {
        if(dfs(x-1, y, 2, 1) == false)
            return false;
    } else if(f == 2 && y <= fl[x-1] && Sum >= J[x]) {
        if(dfs(x-1, y, 1, 1) == false)
            return false;
    } else{
        if(f == 1) {
            if(dfs(x, y+1, f, 0) == false)
                return false;
        } else {    
            if(dfs(x, y-1, f, 0) == false)
                return false;
        }
    }
    return true;
}

int main() {
    cin >> n >> m;
    memset(fl, 0x3F, sizeof(fl));
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++) {
            cin >> mp[i][j];
            if(mp[i][j] == 'J'){
                J[i]++;
                fr[i] = j;
                fl[i] = min(fl[i], j);
                sum++;
            }
        }
    dfs(n, 1, 1, 1);
    cout << cnt;
    return 0;
}
posted @ 2022-11-16 20:25  Simba秋  阅读(47)  评论(0)    收藏  举报