poj 3254

来源:互联网 发布:卖家开通淘宝客的条件 编辑:程序博客网 时间:2024/05/22 05:25

链接:http://poj.org/problem?id=3254
分析:一道经典的状压dp,核心是将排列方式看做01串,用十进制表示
代码:

/*2017-2-11 15:51 author:lian*/#include <iostream>#include <algorithm>#include <cstdlib>#include <cstdio>#include <cstring>using namespace std;typedef long long ll;const int MAX = 100000000;const int N = 15;int probable[1<<N],mapp[N],dp[N][1<<N];bool judge_probale(int i); //保证没有相邻的1bool judge_two(int i,int j);//保证两个排列没有相邻的1int main(){    int n,m,i,j,k;    while(cin>>n>>m)    {        int len = 0;        memset(mapp,0,sizeof(mapp));        for(i=1; i<=n; i++)          for(j=1; j<=m; j++)          {             cin>>k;             mapp[i] += (k<<(j-1));//构造相应的十进制          }        memset(dp,0,sizeof(dp));        for(i=0; i<(1<<m); i++)           if(judge_probale(i))           {               if((i&mapp[1]) == i)                    dp[1][i] = 1;               probable[len++] = i;           }        for(i=1; i<=n; i++)          for(j=0; j<len; j++) //当前的状态          {              for(k=0; k<len; k++) //上一行的状态              {                  if(judge_two(probable[j],probable[k]) == false)                      continue;                  if((probable[j]&mapp[i]) != probable[j])                        break;                  dp[i][probable[j]] += dp[i-1][probable[k]];              }          }          int ans = 0;          for(j=0; j<len; j++)          {                ans += dp[n][probable[j]];                ans %= MAX;          }          cout<<ans<<endl;    }    return 0;}bool judge_probale(int i){    if(i&(i<<1))        return false;    return true;}bool judge_two(int i,int j){    if(i&j)        return false;    return true;}
0 0
原创粉丝点击