ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1879 [USACO06NOV] Corn Fields G

2020-08-12 07:00:16  阅读:283  来源: 互联网

标签:ch 20 int Fields Corn 牧场 土地 USACO06NOV John


题目描述

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

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

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

输入格式

第一行:两个整数M和N,用空格隔开。

第2到第M+1行:每行包含N个用空格隔开的整数,描述了每块土地的状态。第i+1行描述了第i行的土地,所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块土地不适合种草。

输出格式

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

输入输出样例

输入 #1

2 3
1 1 1
0 1 0

输出 #1

9

一道入门的状压dp题,但对于我这种萌新还是太难了,所以写篇博客纪念一下。。。

看到m的范围很小,我们就可以考虑对m进行状态压缩

我们设 \(f[i][j]\) 表示第\(i\)行放置情况为\(j\)的方案数.

我们就可以枚举所有的状态来进行转移

也就是 \(f[i][j] += f[i-1][k]\)

那怎么判断一个状态是否合法呢?

首先,这一行不能选相邻的两列也就是 j & (j<<1) == 0, j & (j>>1) == 0

并且还要与上一行的所选的不能有相邻的即 j & k == 0

那么怎么判断这个状态选的土地是否都合法呢?

我们可以预先处理每一行的初始状态,即对土地能不能选进行状态压缩。

当 s[i] & j == 0 就代表j这个状态可能选了不肥沃的土地。(可以画个图了解一下)

最终答案就是 \(\sum_{i=0}^{i< (1<<m)} f[n][i]\)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int p = 1e8;
int n,m,ans,x,base[20],f[15][35000],zhuangtai[20],map[20][20];
inline int read()
{
	int s = 0, w = 1; char ch = getchar();
	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
	while(ch >= '0' && ch <= '9'){s = s * 10+ch -'0'; ch = getchar();}
	return s * w; 
}
bool judge(int x)//判断x这个状态是否合法
{
	if(x & (x<<1)) return 0;
	if(x & (x>>1)) return 0;
	return 1;
}
int main()
{
	n = read(); m = read();
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			map[i][j] = read();
		}
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			zhuangtai[i] = (zhuangtai[i]<<1) + map[i][j];//把一开始土地能不能选的情况进行状态压缩
		}
	}
	base[0] = 1;
	for(int i = 1; i <= m; i++) base[i] = base[i-1] * 2;
	f[0][0] = 1;
	for(int i = 1; i <= n; i++)
        {
		for(int j = 0; j < base[m]; j++)
		{
			if(judge(j) && ((zhuangtai[i] & j) == j))//j这个状态不能选不肥沃的土地
			{
				for(int k = 0; k < base[m]; k++)
				{
					if(((j&k) == 0) && judge(k))
					{
						f[i][j] += f[i-1][k];//转移
						f[i][j] %= p;
					}
				}
			}
		}
	}
	for(int i = 0; i < base[m]; i++) ans = (ans + f[n][i]) % p;
	printf("%d\n",ans);
	return 0;
}

标签:ch,20,int,Fields,Corn,牧场,土地,USACO06NOV,John
来源: https://www.cnblogs.com/genshy/p/13485231.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有