POJ3254 状压DP入门

题目:http://poj.org/problem?id=3254

因为&运算写成&&--导致调试了快一个小时代的代码没有搞定

关于建图:

1、题目中是1表示可以放牧,0表示不可以放牧,但是建图的时候,可以放牧的位用0表示,不可以放牧的位用1表示。原因如下:

假设可以放牧的位用1表示,不可以放牧的位用0表示,那么假设当前行状态时1010   想要放置1001 ,&运算的结果是1,但是显然不合法,

也就是说  设值状态的意义,以及怎么判断是不是合法,这个在做之前一定考虑清楚再去写,否则改起来很麻烦

如果可以放牧的位用0表示,不可以放牧的位用1表示,那么,合法状态与图的状态想与的结果都是0,从而判断状态

2、由于状态非常多,所以最初存储所有状态的时候,就要去除一部分不合法的状态--相邻位不能为同为1 ,就是(x&(x<<1))不能为1

3、dp[i][j]=segma(dp[i-1][k])   dp[i][j]表示当前设置到第i行,状态为j的方案数, 计算方法是枚举第i-1行的状态,对每一种,枚举第i行的状态

帖代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define reped(i,s,e) for(int i=s;i>=e;i--)
#define arclr(aa,v) memset(aa,v,sizeof(aa))
#define ll long long
#define IN(s) freopen(s, "r", stdin)

const int MAXN = 17;//注意int只有32位
const int MOD = 100000000;

int state[MAXN],mat[MAXN][MAXN];
int all[1<<MAXN],scnt;//记录所有可能的状态用于枚举
ll dp[MAXN][1<<MAXN];
int n,m;
void init()
{
    scnt=0;//所有可能的状态总数
    int tot= (1<<n);
    for(int i=0;i<tot;i++)
        if(!(i & i<<1))//要求相邻不能有1 牛与牛之间不能相邻
            all[scnt++]=i;//存储所有可能的状态,上一个条件排除了很多状态
    memset(dp,0,sizeof(dp));
}

int main()
{
    //IN("poj3254.txt");
    while(~scanf("%d%d",&m,&n))
    {
        init();
        for(int i=1;i<=m;i++)
        {
            state[i]=0;//初始化第i行的状态,0可以放牧,1表示不能放牧
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&mat[i][j]);
                if(!mat[i][j])state[i]+=(1<<(n-j));
            }
        }

        //初始化dp边界
        for(int i=0;i<scnt;i++)
            if(!(all[i]&state[1]))
                dp[1][i]=1;

        for(int i=2;i<=m;i++)
        {
            for(int j=0;j<scnt;j++)
            {
                if((all[j]&state[i]))continue;// 牛必须放在方格1里
                for(int k=0;k<scnt;k++)
                {
                    if((all[k]&state[i-1]))continue;//牛必须放在方格1里
                    if( all[k]&all[j] )continue;//不能有两个1在同一列,两只牛也不能竖着相邻
                    dp[i][j]=(dp[i][j]+dp[i-1][k])%MOD;//
                }
            }
        }

        ll ans=0;
        for(int i=0;i<scnt;i++)
        {
            ans=(ans+dp[m][i])%MOD;
        }
        printf("%lld\n",ans);
    }

    return 0;
}

POJ3254 状压DP入门

时间: 2024-10-11 10:40:07

POJ3254 状压DP入门的相关文章

poj 3254 Corn Fields 状压dp入门

// poj3254 状压dp入门 // dp[i][S]表示前i行第i行状态为S时放牧的情况 // S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数 // 首先dp[0][S]合法的话就是1 // 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态) // 最后的结果就是dp[n][S](S为所有的合法状态) // // 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数 // 这又不是求放羊的数量,这是方

poj 2411 Mondriaan&#39;s Dream 状压dp入门

题意: 求h*w的矩形被1*2的小矩形覆盖的方案数. 分析: 状压dp入门,<挑战程序设计竞赛>上讲的很好,好几天才看懂. 代码: #include <iostream> using namespace std; __int64 ans[16][16]; int n,m; __int64 dp[2][1<<16]; __int64 solve() { int i,j,used; memset(dp,0,sizeof(dp)); __int64 *crt=dp[0],*n

poj3254(状压dp)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19518   Accepted: 10243 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yu

poj3254 状压dp 每行独立 入门水题

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18789   Accepted: 9880 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yum

状压dp入门

(先处理好基本的位运算的东西) 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值.例如3(11)^2(10)=1(01). 4.'<&

POJ3254 状压dp

          Corn Fields Time Limit: 2000MS   Memory Limit: 65536K       Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a

POJ 1185 炮兵阵地(状压DP入门)

http://poj.org/problem?id=1185 状压DP: 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int dp[105][100][100]; 7 int ma[105],st[105]; 8 9 int ok(int x) 10 { 11 return (x&(x<<1))+(x&(x&

状压DP入门——铺砖块

题目描述 现有n*m的一块地板,需要用1*2的砖块去铺满,中间不能留有空隙.问这样方案有多少种 输入 输入n,m(1<=n, m<=11) 有多组输入数据,以m=n=0结束 输出 输出铺砖块的方案数 样例输入 1 2 1 3 1 4 2 2 2 3 2 4 2 11 4 11 0 0 样例输出 1 0 1 2 3 5 144 51205 我A的第一道状压DP题是导游,感觉就是背包~~ 此题不是很懂 此题状压DP,DP[i][sta]表示前i行填满对第i+1行的影响为状态sta时的方案总数 易知

poj 2441 Arrange the Bulls(状压DP入门)

Arrange the Bulls Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 3509   Accepted: 1344 Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to play basketball with the other bulls because the