poj 3154 Corn Fields

来源:互联网 发布:auxre 如何设计软件 编辑:程序博客网 时间:2024/06/06 03:15
http://poj.org/problem?id=3254
题意:有n行m列的矩阵,只能有0和1两种数字,现在准备在矩阵上放母牛(只能放在1上),问有多少种分配方案,
使得没有牛相邻。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
#define MM(a) memset(a,0,sizeof(a))
typedef long long ll;
typedef unsigned long long ULL;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f;
const int big=50000;
const int mod=100000000;
int max(int a,int b) {return a>b?a:b;};
int min(int a,int b) {return a<b?a:b;};
const int N = 500;
const int M=20000;
int fi[15][15],dp[15][(1<<13)+10];

int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
memset(dp,0,sizeof(dp));
dp[0][0]=1;//这个初始化很重要!!而不能将所有的dp[0]都初始化为 1

for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&fi[i][j]);
//cout<<"////3\n";
for(int i=1;i<=n;i++)
for(int j=0;j<=(1<<m)-1;j++)
{
int flag=1;
if(j&(j>>1)||j&(j<<1))
continue;//枚举的j没有1相邻
for(int k=1;k<=m;k++)
if(!fi[i][m-k+1]&&((j>>(k-1))&1))
{
flag=0;
break;
}//枚举的j不与矩阵冲突

if(!flag)
continue;
//cout<<"////2\n";
for(int k=0;k<=(1<<m)-1;k++)
if(dp[i-1][k]&&!(k&j))
dp[i][j]+=dp[i-1][k];

}
long long ans=0;
for(int i=0;i<=(1<<m)-1;i++)
ans=(ans+dp[n][i])%mod;
/*for(int j=0;j<=(1<<m)-1;j++)
cout<<j<<" "<<dp[n][j]<<"\n";
*/
printf("%lld\n",ans);
}
return 0;
}


分析:dp[i][j]扫到第i层选取状态为j时的状态数,dp[i][j]+=dp[i-1][k](k为前一行符合要求的状态)
扫到第i行时,枚举当前状态,再枚举前一状态,要是符合要求的话就相加
wa代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <map>
    #include <algorithm>
    #include <set>
    using namespace std;
    #define MM(a) memset(a,0,sizeof(a))
    typedef long long ll;
    typedef unsigned long long ULL;
    const double eps = 1e-10;
    const int inf = 0x3f3f3f3f;
    const int big=50000;
    const int mod=100000000;
    int max(int a,int b) {return a>b?a:b;};
    int min(int a,int b) {return a<b?a:b;};
    const int N = 500;
    const int M=20000;
    int fi[15][15],dp[15][1<<(12)+5];
    //dp[i][j]+=

    int main()
    {
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
    memset(dp,0,sizeof(dp));
    fill(dp[1],dp[1]+m,1);
    for(int i=1;i<=n;i++)
    for(int j=1;i<=m;j++)
    scanf("%d",&fi[i][j]);

    for(int i=1;i<=n;i++)
    for(int j=0;j<=(1<<m)-1;j++)
    {
    int flag=1;
    if(j&(j>>1)||j&(j<<1))
    continue;
    for(int k=1;k<=m;k++)
    if(!fi[i][k]&&((j>>(k-1))&1))
    {
    flag=0;
    break;
    }
    if(!flag)
    continue;

    for(int k=0;k<=(1<<m)-1;k++)
    if(dp[i-1][k]&&!(i&j))
    dp[i][j]+=dp[i-1][k];

    }
    long long ans=0;
    for(int i=0;i<=(1<<m)-1;i++)
    ans=(ans+dp[n][i])%mod;
    printf("%lld\n",ans);
    }
    return 0;
    }