题解——[USACO06NOV]玉米田Corn Fields 状压DP

题面:

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

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

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

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

题解:

emmm。。。一道不难的状压DP

设f[i][j]表示到i行,状态为j的方案数,

因为相邻两块土地不能选,所以我们可以先dfs搜出所有可能状态,

这样状态数暴跌10倍,,,貌似很划得来的样子,不过不这样好像也可以,但是DP判断的地方也会麻烦一些。。。

然后存下不能放的地方,并标记为1,(同样用状压)

依次枚举行,当前状态,上一行状态,统计并取模即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R register int
 4 #define AC 15
 5 #define LL long long
 6 #define mod 100000000
 7 int n,m,tmp,ans,tot;
 8 int f[AC][400],s[AC],num[400];//error!!!状态要开400,,,
 9
10
11 void pre()
12 {
13     int a;
14     scanf("%d%d",&n,&m);
15     for(R i=1;i<=n;i++)
16         for(R j=1;j<=m;j++)
17         {
18             scanf("%d",&a);
19             if(!a)    s[i] |= 1 << (m - j);//给定状态也要压
20         }
21 }
22
23 void dfs(int x,int now)
24 {
25     if(x)    tmp+=1 << (m - now);
26     if(now == m)
27     {
28         num[++tot]=tmp;
29         if(x) tmp-=1 << (m - now);
30         return ;
31     }
32     if(x) dfs(0,now+1);
33     else
34     {
35         dfs(0,now+1);
36         dfs(1,now+1);
37     }
38     if(x)     tmp-=1 << (m - now);
39 }
40
41 void work()
42 {
43     for(R i=1;i<=tot;i++)//第一行特殊处理
44     {
45         if(s[1] & num[i]) continue;
46         f[1][i]=1;
47     }
48     for(R i=2;i<=n;i++)//枚举行
49     {
50         for(R j=1;j<=tot;j++)//枚举当前行状态
51         {
52             if(s[i] & num[j]) continue;
53             for(R k=1;k<=tot;k++)//枚举上一行状态
54             {
55                 if(s[i-1] & num[k]) continue;
56                 if(num[j] & num[k]) continue;
57                 f[i][j] += f[i-1][k];
58                 f[i][j] %= mod;
59                 //if(f[i][j] > mod) f[i][j] -= mod;
60             }
61         }
62     }
63     for(R i=1;i<=tot;i++)
64     {
65         ans+=f[n][i];
66         ans%=mod;
67         //if(ans > mod) ans-=mod;
68     }
69     printf("%d\n",ans);
70 }
71
72 int main()
73 {
74 //    freopen("in.in","r",stdin);
75     pre();
76     dfs(1,1);//获取所有有效状态
77     dfs(0,1);
78     work();
79     //fclose(stdin);
80     return 0;
81 }

原文地址:https://www.cnblogs.com/ww3113306/p/9097805.html

时间: 2024-08-03 08:34:10

题解——[USACO06NOV]玉米田Corn Fields 状压DP的相关文章

P1879 [USACO06NOV]玉米田Corn Fields 状压dp

链接在此! 正解:状压dp(emm……据说插头dp也可以趴但我不管!!!不会!!! 解题报告: ……我真的太菜了……我以为一个小时前要搞完的题目调错误调了一个小时……90分到100我差不多搞了一个小时…… 然后这题还是做过的……就很气,觉得确实是要搞下博客没事儿复习下不然做过的题目还花俩小时我真的哭死…… 先放上错误的90分代码讲一下错哪儿了(因为……其实100并不难是可以想到的……没有太大讲的意义,主要我太菜了所以才会搞这么久TT 点我♂看♂沙雕灵巧在线WA题 然后错误的点是最后一个点RE,开

[USACO06NOV]玉米田Corn Fields (状压$dp$)

题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 块草皮,且最后一位状态为 \(k\) . 同时多记录一个每一列中的不能放的位置 \(w[i]\). 然后就可以很轻松的转移了... 转移方程看代码. Code #include<bits/stdc++.h> #define ll long long using namespace std; ll f[13][145][10000],n,K; ll js[1000

洛谷 P1879 [USACO06NOV]玉米田Corn Fields

P1879 [USACO06NOV]玉米田Corn Fields 题目描述 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

P1879 [USACO06NOV]玉米田Corn Fields

P1879 [USACO06NOV]玉米田Corn Fields 这道题跟互不侵犯差不多,但是数据范围更大了 对于状态压缩dp,提前枚举出转移是一种很好的优化 然后对于转移也需要仔仔细细的分析,如同期望dp #include<cstdio> #include<algorithm> #include<iostream> const int mod=1e8; int map[20]; long long f[2][1<<12]; int b[400],tot;

【luogu P1879 [USACO06NOV]玉米田Corn Fields】 题解

题目链接:https://www.luogu.org/problemnew/show/P1879 状压DP. 设dp[i][j]表示第i行,状态为j的方案数 初始dp[0][0] = 1 这样一共12行12列,最多1<<12. 这样转移时,只要满足上下没有两个1,这两行分别满足没有相邻1. 加法原理转移. $ j&k==0 $ $ dp[i][j] += dp[i-1][k] $ #include <cstdio> #include <cstring> #inc

【p1879】[USACO06NOV]玉米田Corn Fields

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

POJ 1684 Corn Fields(状压dp)

描述 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

POJ 3254 Corn Fields 状压DP

链接:http://poj.org/problem?id=3254 题意:一块M*N的田地,每小块地大小是1*1,可以种植物的标记为1,不可以种植物的标记为0,并且相邻的两块地不可以同时种植物.问题是有多少种不同的种植方案(所有地都不种也是一种种植方案) 思路:这是第一道状压DP题,从第一行更新到最后一行,每一行用一个N位的二进制数来表示该行的状态1表示该位置种了植物,0表示该位置没种植物.因为每块地只对相邻的土地能否种植有所影响,所以每一行的状态可以用前一行的状态递推得到. 资料:http:/

poj 3254 Corn Fields 状压dp入门

// poj3254 状压dp入门 // dp[i][S]表示前i行第i行状态为S时放牧的情况 // S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数 // 首先dp[0][S]合法的话就是1 // 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态) // 最后的结果就是dp[n][S](S为所有的合法状态) // // 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数 // 这又不是求放羊的数量,这是方