bzoj1725: [Usaco2006 Nov]Corn Fields牧场的安排(状态压缩DP)

本来就是一个写不大来动态规划的人,结果现在又了解到还有种东西叫状态压缩dp,唉。。。

找了一道例题来试试看:http://www.lydsy.com/JudgeOnline/problem.php?id=1725

解:我们用f[i][j]来表示当前第i行,状态为j的情况下,(且之前的1~i-1的方案数已经确定了),前i行有多少种方案,那么动态转移方程其实很明显:

f[i][j]=sum(f[i-1][k]);(当上一行为第k种状态且与当前枚举的第i种状态不会产生相邻的土地,就加上f[i-1][k]的方案数)

方程好写,可是状态很难表达啊,我们总不能开一个12维的数组吧。。。

所以我们就利用了它的表达要么是0,要么是1,的这个特点用二进制解决。

首先我们来看样例数据,和如何预处理:

输入:

2 3

1 1 1

0 1 0

输出:

9

scanf("%d%d",&m,&n);
  for (int i=1;i<=m;i++)
   for (int j=n;j>=1;j--)
   {
        scanf("%d",&now);
        if (now==1) a[i]=a[i]|(1<<(j-1));
   }

这段代码就是把输入数据当成二进制并转换成十进制,如第一行储存为7,第二行储存为2。方便接下来的操作

sum=(1<<n)-1;
   for (int j=0;j<=sum;j++)
    if (((a[1]|j)==a[1])&&((j&(j<<1))==0))  dp[1][j]++;

哈这段代码就蛮重要的啦

dp[i][j]之前就讲过了它的意思,那么j状态具体指什么呢??

比如dp[2][6]就表示我们把第二行种成1 1 0这种样子能获取的方案数,将j转换成2进制,就形象的代表了一种种草的形态。

如j为2是表示0 1 0这种状态。

那么我们就先预处理第一行在各种种草状态下是否符合题目要求,枚举j这种状态,须符合以下两点才是合法的:

1.这种 状态本身不能有两个相邻的1,比如说1 1 0就不可以因为这样把两块草场种在了一起。

//具体实现方法,我们把原本状态与当前枚举状态取或,如果说a[i]的值变化了,说明它有哪块地方原本为0,不允许种,但是当前情况却种了,导致那块草场变为了1

2.这种状态要符合开始的输入,比如说我们枚举第二行为1 0 0就是不可以的,因为它原本是0 1 0,第一位是不允许种草的,咱不能硬种啊。。。

//将当前状态左移或者右移(这个随便你),再与没移之前的状态进行and,如果答案为0,说明它这个状态没有相邻的可种草场,否则一定会有哪一块是1.

符合以上两点,方案数就可以加1;

然后我们正式进行dp,枚举当前的行与状态(请保证它是合法的,和第一行的判断方法一样),并且枚举上一行的状态,两个状态and一下,如果合法就加上上一行这种情况下的方案。

恩,大概就是这样,发觉自己讲的好乱,,,,

那下面是程序:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int m,n,now,sum;
int a[100],dp[20][10000];
int main()
{
  scanf("%d%d",&m,&n);
  for (int i=1;i<=m;i++)
   for (int j=n;j>=1;j--)
   {
        scanf("%d",&now);
        if (now==1) a[i]=a[i]|(1<<(j-1));
   }
  sum=(1<<n)-1;
   for (int j=0;j<=sum;j++)
    if (((a[1]|j)==a[1])&&((j&(j<<1))==0))  dp[1][j]++;
  for (int i=2;i<=m;i++)
   for (int j=0;j<=sum;j++)
   if (((a[i]|j)==a[i])&&((j&(j<<1))==0))
   {
        for (int k=0;k<=sum;k++)
        if ((j&k)==0) dp[i][j]=(dp[i][j]+dp[i-1][k])%100000000;
   }
   int ans=0;
   for (int j=0;j<=sum;j++) ans=(ans+dp[m][j])%100000000;
   cout<<ans<<endl;
   return 0;
}
时间: 2024-10-12 03:34:56

bzoj1725: [Usaco2006 Nov]Corn Fields牧场的安排(状态压缩DP)的相关文章

bzoj1725 [Usaco2006 Nov]Corn Fields牧场的安排(状压dp)

1725: [Usaco2006 Nov]Corn Fields牧场的安排 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 714  Solved: 502[Submit][Status][Discuss] Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是

【BZOJ1725】[Usaco2006 Nov]Corn Fields牧场的安排 状压DP

[BZOJ1725][Usaco2006 Nov]Corn Fields牧场的安排 Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫瘠,不能用来放牧.并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边.当然,FJ还没有决定在哪些土地

BZOJ1725: [Usaco2006 Nov]Corn Fields牧场的安排

1725: [Usaco2006 Nov]Corn Fields牧场的安排 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 400  Solved: 290[Submit][Status] Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫

【bzoj1725】[USACO2006 Nov]Corn Fields牧场的安排

题目描述 Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫瘠,不能用来放牧.并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边.当然,FJ还没有决定在哪些土地上种草. 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供

BZOJ 1725: [Usaco2006 Nov]Corn Fields牧场的安排

Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫瘠,不能用来放牧.并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边.当然,FJ还没有决定在哪些土地上种草. 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少

[Usaco2006 Nov]Corn Fields牧场的安排

题目描述 Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫瘠,不能用来放牧.并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边.当然,FJ还没有决定在哪些土地上种草. 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供

【BZOJ】1725: [Usaco2006 Nov]Corn Fields牧场的安排

[算法]状压DP [题解]对于上一行的每个状态,每行进行DFS. #include<cstdio> #include<algorithm> #include<cstring> #define ll long long using namespace std; const int maxn=20,maxN=10000,MOD=100000000; ll f[2][maxN]; int n,m,x,h; bool map[maxn][maxn]; void dfs(int

【bzoj1725/Usaco2006 Nov】Corn Fields牧场的安排——状压dp

Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫瘠,不能用来放牧.并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边.当然,FJ还没有决定在哪些土地上种草. 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少

【状压DP】BZOJ 1725 Usaco Corn Fields牧场的安排

题目和SCOI互不侵犯 很相似,感觉棋盘形的状压DP主要在于预处理状态.转移以及判断倒不是很难. #include <cstdio> #include <algorithm> const int State = (1<<12)+5; const int MOD = 100000000; int n,m,Count; int dp[20][State],Map[20]; int num[State],now[State]; bool Can[State][State];