牛客假日团队赛3 - CornFields (状压DP)

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

链接:https://ac.nowcoder.com/acm/contest/945/E
来源:牛客网

题目描述

Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can’t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

输入描述:

Line 1: two space-separated integers M and N
Lines 2… M+1: row I +1 describes each cell in row I of the ranch, N space-separated integers indicating whether the cell can be planted (1 means fertile and suitable for planting, 0 means barren and not suitable for planting).

输出描述:

Line 1: an integer: FJ total number of alternatives divided by a remainder of 100,000,000.

示例1

2 3
1 1 1
0 1 0

输出

9

解题思路:

将每一行的数都压缩成一个十进制的状态,如 1 1 1的十进制是7,则用7来表示这个状态。
将每行suitable for planting的点记录为0(比1更方便判断是否可以基于这个构造一种可能的solution,一开始记为1, WA了几发,后来发现还是记为0方便)
上下两行会冲突,用 a&b != 0 表示
是否有可能配制成目标情况, 如第二行 0 1 0, 则不可能配成1 1 0 (第一个不行)或是 0 1 1 (第三个不行)或是别的 (base & to) == 0 表示可行。

状态转移方程;
dp[i][j]表示第i行,j状态的可行解数目
d p [ i ] [ j ] = f o r   a l l   k   w h i c h    a r e   v a l i d    f o r    r o w    i 1   a n d    c o m p a t i b l e   f o r   c o n d i t i o n   j d p [ i 1 ] [ k ] dp[i][j] = \sum\limits_{for\,all\,k\,which\,\,are\,valid\,\,for\,\,row\,\,i - 1\,and\,\,compatible\,for\,condition\,j} {dp[i - 1][k]}

AC Code:

/*
 * Copyright (c) 2019 Ng Kimbing, HNU, All rights reserved. May not be used, modified, or copied without permission.
 * @Author: Ng Kimbing, HNU.
 * @LastModified:2019-06-25 T 11:09:41.155 +08:00
 */
package ACMProblems.QianDaoTi;

import static ACMProblems.ACMIO.*;

/*
 * 链接:https://ac.nowcoder.com/acm/contest/945/E
 * 来源:牛客网
 *
 * ## 题目描述 
 * Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can't be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
 * Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.
 * ## 输入描述:
 * Line 1: two space-separated integers M and N
 * Lines 2.. M+1: row I +1 describes each cell in row I of the ranch, N space-separated integers indicating whether the cell can be planted (1 means fertile and suitable for planting, 0 means barren and not suitable for planting).
 * ## 输出描述:
 * Line 1: an integer: FJ total number of alternatives divided by a remainder of 100,000,000.
 * ## 示例1
 * >2 3
 * 1 1 1
 * 0 1 0
 *
 * ## 输出
 * >9
 *
 * ## 解题思路:
 * 将每一行的数都压缩成一个十进制的状态,如 1 1 1的十进制是7,则用7来表示这个状态。
 * 将每行suitable for planting的点记录为0(比1更方便判断是否可以基于这个构造一种可能的solution,一开始记为1, WA了几发,后来发现还是记为0方便)
 * 上下两行会冲突,用 a&b != 0 表示
 * 是否有可能配制成目标情况, 如第二行 0 1 0, 则不可能配成1 1 0 (第一个不行)或是 0 1 1 (第三个不行)或是别的 (base & to) == 0 表示可行。
 */
public class BitDp {
    private static final int MOD = 100000000;
    private static int[] row = new int[13];
    private static int[] validList = new int[400];
    private static int[][] dp = new int[13][400];

    private static int not(int foo) {
        return foo == 0 ? 1 : 0;
    }

    public static void main(String[] args) throws Exception {
        setStream(System.in);
        int rowNum = nextInt();
        int colNum = nextInt();// col Num
        for (int i = 0; i < rowNum; i++)
            for (int j = 0; j < colNum; j++)
                row[i] = (row[i] << 1) | not(nextInt());
        int maxCondition = 1 << 12, k = 0;
        for (int i = 0; i < maxCondition; i++)
            if ((i & (i << 1)) == 0)
                validList[k++] = i;
//        System.out.println(Arrays.toString(validList));
        validList[k] = maxCondition;
        maxCondition = 1 << colNum;
        for (int i = 0; validList[i] < maxCondition; i++)
            if (settable(row[0], validList[i]))
                dp[0][i] = 1;
        for (int r = 1; r < rowNum; r++)
            processRow(r, maxCondition);
        int theLastRow = rowNum - 1;
        int ans = 0;
        for (int i = 0; validList[i] < maxCondition; ++i)
            ans = (ans + dp[theLastRow][i]) % MOD;
        System.out.println(ans);
    }

    private static boolean settable(int base, int to) {
        return (base & to) == 0;
    }

    private static boolean willConflict(int a, int b) {
        return (a & b) != 0;
    }

    private static void processRow(int r, int maxCondition) {
        // for each valid case
        for (int i = 0; validList[i] < maxCondition; i++) {
            if (dp[r - 1][i] == 0)
                continue;
            int tryLastRow = validList[i];
            // is settable
            if (!settable(row[r - 1], tryLastRow))
                continue;
            // list[i] is valid.
            for (int j = 0; validList[j] < maxCondition; j++) {
                int tryThisRow = validList[j];
                if (settable(row[r], tryThisRow) && !willConflict(tryLastRow, tryThisRow))
                    dp[r][j] = (dp[r][j] + dp[r - 1][i]) % MOD;  // += last row valid num
            }
        }
    }
}


猜你喜欢

转载自blog.csdn.net/weixin_44090305/article/details/93600258