状态压缩第二弹
http://blog.csdn.net/harrypoirot/article/details/23163485?utm_source=tuicool
先贴个这个题的详解,写的真的非常非常的好,以他为借鉴,来写的题
PS:我发现我现在养成了看题解的毛病,现在基本上不看题解过不了题,哎,该怎么办呢?好懊恼 :(
#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<stack>
#include<set>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#define ll __int64
#define lll unsigned long long
#define llf long double
#define MAX 600
#define eps 1e-8
#define mod 100000000
using namespace std;
/*
1是不可放,0是可放
*/
int dp[50][MAX];//前i行,第j状态的方案数
int status[MAX];//状态数
int ma[50];
int n,m;
int k;
int lr(int x)
{
if(x&x<<1)return 0;//如果10进制X有相邻的1,不符合
return 1;
}
void init()//枚举可行状态
{
k = 0;
for(int i = 0; i<(1<<m); i++)
{
if(lr(i))
{
status[k++] = i;
}
}
}
int main()
{
int num;
while(~scanf("%d%d",&n,&m))
{
init();
memset(dp,0,sizeof(dp));
for(int i = 1; i<=n; i++)
{
ma[i] = 0;
for(int j = 1; j<=m; j++)
{
scanf("%d",&num);
if(num==0)
{
ma[i] += (1<<(m-j));//记录给出的状态
}
}
//cout<<ma[i]<<endl;
}
// for(int i = 0; i<k; i++)
// {
// cout<<status[i]<<endl;
// }
for(int i = 0; i<k; i++)
{
if(!(ma[1]&status[i]))//如果与可行状态相同,dp[1][i] = 1;
dp[1][i] = 1;
}
for(int i = 2; i<=n; i++)
{
for(int j = 0; j<k; j++)
{
if(ma[i]&status[j])continue;//枚举i行可行状态
for(int l = 0; l<k; l++)
{
if(ma[i-1]&status[l])continue;//枚举i-1行可行状态
if(status[j]&status[l])continue;//看两个枚举的状态是否相同
dp[i][j]= (dp[i][j] + dp[i-1][l])%mod;
}
}
}
int ans = 0;
for(int i = 0; i<k; i++)
{
// cout<<dp[n][i]<<endl;
ans= (ans + dp[n][i])%mod;
}
printf("%d\n",ans);
}
return 0;
}
具体的题解我就不写了,这个就是给自己当个笔记