Corn Fields----状压DP

本文探讨了一个有趣的问题:如何在一块矩形的土地上种植玉米,使得相邻的地块不会被种植,同时考虑部分地块可能不适合种植的情况。文章通过动态规划的方法解决了这个问题,并提供了一段详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Corn Fields
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 14230 Accepted: 7460

Description

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.

Input

Line 1: Two space-separated integers:  M and  N 
Lines 2.. M+1: Line  i+1 describes row  i of the pasture with  N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)

Output

Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.

Sample Input

2 3
1 1 1
0 1 0

Sample Output

9

Hint

Number the squares as follows:
1 2 3
  4  

There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.

Source

题目链接:http://poj.org/problem?id=3254


我昨天晚上推了一晚上,然后就GG了,今早来了实验室看了大牛博客,恍然大悟,不得不说,大牛对位运算的操作已经登峰造极,炉火纯青了。


题目的意思是说有个农夫买了一块矩形的地分成小块要给他的牛种玉米,有一些小矩形并不能够种玉米,而且种玉米有一个规则就是种玉米的地不能够相邻。


放上大牛的链接吧,太厉害了:http://www.cnblogs.com/buptLizer/archive/2012/08/22/2650717.html


我就注释一下代码吧。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#define mod 100000000
using namespace std;
const int MAXN=13;
const int MAXSTATE=(1<<12)+10;
int map1[MAXN][MAXN];
int ans[MAXSTATE];
int dp[MAXN][MAXSTATE];
int num,row,col;
void fax(){//这个函数是求在不管土地是否能够种玉米的情况下合法的状态
    for(int i=0;i<(1<<col);i++){
        if((i&(i<<1))==0){//不可相邻
            ans[num++]=i;
        }
    }
}
bool judge(int state,int r){//判断state状态和第i行土地是否矛盾
    int rstate=0;//第i行土地的状态
    for(int i=1;i<=col;i++){
        if(map1[r][i])
            rstate+=(1<<(col-i));
    }
    if(!(state&(~rstate)))//仔细推敲一下这里的取反,大牛的位运算就是牛,想想看,如果不取反则有的情况则会矛盾
        return true;
    return false;
}
int main(){
    while(~scanf("%d%d",&row,&col)){
        memset(dp,0,sizeof(dp));
        num=0;
        for(int i=1;i<=row;i++){
            for(int j=1;j<=col;j++){
                scanf("%d",&map1[i][j]);
            }
        }
        fax();
        dp[0][0]=1;
        for(int i=1;i<=row;i++){
            for(int st=0;st<num;st++){//当前行的状态
                if(judge(ans[st],i)){
                    for(int pst=0;pst<num;pst++){//上一行的状态
                        if(judge(ans[pst],i-1)&&!(ans[st]&ans[pst])){
                            dp[i][ans[st]]+=dp[i-1][ans[pst]];
                        }
                    }
                }
            }
        }
        int cnt=0;
        for(int i=0;i<num;i++){
            cnt=(cnt+dp[row][ans[i]])%mod;
        }
        cout<<cnt<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值