P1879 [USACO06NOV]玉米田Corn Fields

https://www.luogu.org/problemnew/show/P1879

状压DP入门题

先压缩状态,再判断所有状态的可行性,状态数为1<<12

判断(i&(i<<1))==0 && (i&(i>>1))==0  此时就是合法状态 即一排中不会有相邻的两块草地

再纵向找,如果第i行的某一状态和i-1行的某一状态 的&值为0 则说明上下无相邻草地

此时再再判断 这个时候的草地分配情况是否违反开始的草地情况,即保证此时状态不要有不合法的

逐行累加取模即可,最后把所有状态的值加到一块

#include
using namespace std;
const int mod = 1e8;
int m,n,a[13][13],s[13],f[(1<<12)+10],dp[13][(1<<12)+10];
int main()
{
	cin >> m >> n;
	for(int i = 1;i <= m;i ++){
		for(int j = 1;j <= n;j ++){
			cin >> a[i][j];
		}
	}
	//压缩状态 
	for(int i = 1;i <= m;i ++){
		for(int j = 1;j <= n;j ++){
			s[i] = (s[i]<<1) + a[i][j];
		}
	}
	//判断所以状态的合法性
	for(int i = 0;i < (1<<12);i ++){
		if((i&(i<<1))==0 && (i&(i>>1))==0) f[i] = 1;
	} 
	dp[0][0] = 1;
	for(int i = 1;i <= m;i ++){
		for(int j = 0;j < (1<<12);j ++){
			if(f[j] && (j&s[i])==j){
				for(int k = 0;k < (1<<12);k ++){
					//上下两行无相邻的情况 
					if((k&j)==0){
						dp[i][j] = (dp[i][j] + dp[i-1][k])%mod;
					}
				}
			}
		}
	}
	int ans = 0;
	for(int i = 0;i < (1<<12);i ++){
		ans += dp[m][i];
		ans %= mod;
	}
	cout << ans;
	return 0;
}

 

你可能感兴趣的:(动态规划)