USACO06NOV玉米田 Corn Fields

题目描述

农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地。John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。

遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。

John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案)

输入格式
第一行:两个整数M和N,用空格隔开。

第2到第M+1行:每行包含N个用空格隔开的整数,描述了每块土地的状态。第i+1行描述了第i行的土地,所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块土地不适合种草。

输出格式
一个整数,即牧场分配总方案数除以100,000,000的余数。

输入输出样例
输入
2 3
0 1 1
1 1 0
输出
8

import java.util.Scanner;

public class CodingExam {
    private static int res = 0;  // 记录方案数
    private static int[] dx = {-1,1,0,0};  // 上下左右 四个方向
    private static int[] dy = {0,0,-1,1};

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int M = sc.nextInt();  // M行
        int N = sc.nextInt();   // N列
        String line = sc.nextLine();  // 读取空行
        int[][] a = new int[M][N];
        for (int i=0;i<M;i++) {
            String[] nums = sc.nextLine().split(" ");
            for (int j=0;j<N;j++) {
                a[i][j] = Integer.parseInt(nums[j]);
            }
         }
        solve(a);
        int mod = 100000000;
        res = res % mod;
        System.out.println(res);
    }

    public static void solve(int[][] a) {
        boolean[][] vis = new boolean[a.length][a[0].length];  // 访问记录数组
        dfs(a, 0, 0, vis);
    }

    public static void dfs(int[][] a, int r, int c, boolean[][] v) {
        // 判断不满足条件的情况
        boolean flag = true;   // flag表示当前情况是否可行
        if (a[r][c] == 1) {    // 当a[r][c]=1时,表示可以种植,需要判断如果它种植了,会不会和上下左右四个方向的其他种植点冲突,如果冲突了,flag=false,需要和a[r][c]=0的情况一起处理
            for (int i=0;i<4 && flag;i++) {
                int tmpR = r + dx[i];
                int tmpC = c + dy[i];
                // 边界出了不影响flag 继续搜索其他方向
                if (tmpR >= 0 && tmpR < a.length && tmpC >=0 && tmpC < a[0].length && v[tmpR][tmpC] && a[tmpR][tmpC] == 1) {
                    flag = false;
                }
            }
        }

        // 每行每列搜 注意换行
        int nextR = r;  // 下次搜索的行
        int nextC = c + 1;   // 下次搜索的列
        if (nextC == a[0].length) {
            nextR = nextR + 1;    // 换行
            nextC = 0;            // 列更新为0
        }
        if (nextR == a.length) {   // 结束条件
            res++;      // 记录结果
            return;
        }

        // 判断 位置是1或0
        if (a[r][c] == 0 || !flag) {  // 条件:1.当前位置a[r][c]=0,不能种 2.当前位置a[r][c]=1,但是flag=false
            dfs(a, nextR, nextC, v);
        }else {              // 如果 当前位置a[r][c]=1 则有两种选择 种/不种
            dfs(a, nextR, nextC, v);  // 不种
            v[r][c] = true;  // 种
            dfs(a, nextR, nextC, v);
            v[r][c] = false;  // 恢复现场
        }

    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值