玉米田(HG 2018.4.22 T2)

hicc0305

2018-04-22 14:28:05

Personal

### 【题目描述】 FJ 购买了一处肥沃的矩形牧场,分成 M N(1 M 12; 1 N 12) 个格子。他想在那里的一些格子中种植美味的玉米。遗憾的是,有些格子区域的土地是贫瘠的,不能耕种。 精明的 FJ 知道奶牛们进食时不喜欢和别的牛相邻,所以一旦在一个格子中种植玉米,那么他就不会在相邻的格子中种植,即没有两个被选中的格子拥有公共边。他还没有最终确定哪些格子要选择种植玉米。 作为一个思想开明的人,FJ 希望考虑所有可行的选择格子种植方案。由于太开明,他 还考虑一个格子都不选择的种植方案!请帮助 FJ 确定种植方案总数。 ### 【输入格式】 第一行包括两个用空格分隔的整数 M 和 N。 接下来的 M 行,每行 N 个数,描述了每行格子是否可以种植的情况(1 表示肥沃的、 适合种植,0 表示贫瘠的、不可种植)。 ### 【输出格式】 输出一个整数,表示 FJ 可选择的方案总数 mod 108 的结果。 ### 【输入输出样例】 cowfood.in 2 3 1 1 1 0 1 0 cowfood.out 9 ### 【 数据规模与约定 】 对于 60% 的数据,1 ≤ M,N ≤ 6 对于 100% 的数据,1 ≤ M,N ≤ 12 ------------ ------------ ------------ 同Mondriaan的梦(HG 2018.4.15 试题1 T3) 状压DP一道。用f[i][j]表示第i行状态为j时的方案数。j依然是个二进制数 f[i][j]通过f[i-1][k]转移过来,k是i-1行合法的所有状态(即不和j冲突) 注意:在dfs前先要判断枚举的j是否合法。 ```cpp #include<map> #include<set> #include<list> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define MOD 100000000 int n,m; int a[13][13],f[13][1<<13]; void dfs(int i,int j,int p,int s) { if(p>m) return; if(p==m) { f[i][j]=(f[i][j]+f[i-1][s])%MOD; return; } if((j & (1 << p))==0) { dfs(i,j,p+1,s); dfs(i,j,min(m,p+2),s | (1<<p)); //p+2:保证相邻的两位不会同时种植,种了第p位,p+1必然是不种,可直接跳过 } else dfs(i,j,p+1,s); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]); f[0][0]=1; for(int i=1;i<=n+1;i++) for(int j=0;j< (1<<m) ;j++) { int flag=1; for(int k=0;k<m;k++) { if((j & (1<<k)) && a[i][k+1]==0)//如果第k位要种,但是土地贫瘠,不行 { flag=0; break; } if((j & (1<<k)) && (j & (1<<(k+1))))//如果有相邻的两位要种,不行 { flag=0; break; } } if(flag) { dfs(i,j,0,0); } } printf("%d",f[n+1][0]); fclose(stdin); fclose(stdout); return 0; } ``` 经过这一道题得出的结论:括号一定不能少加,千万不要为了压行而压行,会死的很惨的