程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3254 狀壓DP,poj3254壓dp

POJ 3254 狀壓DP,poj3254壓dp

編輯:C++入門知識

POJ 3254 狀壓DP,poj3254壓dp


題目大意: 一個農民有一片n行m列 的農場   n和m 范圍[1,12]  對於每一塊土地 ,1代表可以種地,0代表不能種。 因為農夫要種草喂牛,牛吃草不能挨著,所以農夫種菜的每一塊都不能有公共邊。 告訴你 n ,m 和那些地方能種菜哪些地方不能種菜,求農夫一共有多少種方案種菜

 

解法:

 

基本思想是狀壓 也就是用一個int 型的數代表一行的種菜策略,二進制的0代表該位不能種菜,1位代表能種菜,使用位運算使處理速度變快

對於單行行,最多有2^12 種情況,並且 2^12種情況裡面還有很多不滿足題意的  篩選一下每行最多有400左右種情況,

1 先篩選出每行滿足題意的情況 

2 如何判斷兩行能否相鄰? 如果一行狀壓的數使 i 另一行狀壓的數是 j  如果 i|j ==i+j 說明兩行可以相鄰

3  如何判斷一個種法能否滿足某一行的要求?  

以樣例來看

2 3

1 1 1

0 1 0

第一行二進制是7 第二行二進制是2 

如果一個種菜的決策時 i  如果 i|2==2 就說明他能滿足第二行的要求,,

 

然後就是dp[i][k] 代表第i行像k這樣種菜的情況數

 

然後就是渣渣參考代碼  g++  

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <string>
#include <queue>
#include <cstring>
#define CL(a,b) memset(a,b,sizeof(a))
#define ll __int64
#define TEST cout<<"TEST   ***"<<endl;
#define INF 0x7fffffff
#define MOD 100000000
using namespace std;

ll dp[15][1000];
int inn[4100],m,n;
int num[12];

int initinn()
{
    int i,j,preinn,nowinn,taginn;
    CL(inn,0);
    for(i=0;i<4100;i++)
    {
        preinn=0,taginn=1;
        j=i;
        while(j)
        {
            nowinn=j&1;
            if(nowinn==1&&preinn==1)
            {
                taginn=0;
                break;
            }
            preinn=nowinn;
            j/=2;
        }
        inn[i]=taginn;
    }
    i=0;j=0;
    while(j<4100)
    {
        if(inn[j]==1)
        {
            inn[i++]=j;
        }
        j++;
    }
    return i;
}

using namespace std;

int main()
{
    initinn();
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int i,j,k,ma=(1<<m)-1;
        int a,sum;
        CL(dp,0);
        for(i=1;i<=n;i++)
        {
            sum=0;
            for(j=0;j<m;j++)
            {
                scanf("%d",&a);
                sum*=2;
                sum+=a;
            }
            num[i]=sum;
        }
        dp[0][0]=1;
        for(i=1;i<=n;i++)
        {
            for(j=0;inn[j]<=ma;j++)
            {
                if((inn[j]|num[i])!=num[i])continue;
                for(k=0;inn[k]<=ma;k++)
                {
                    if((inn[j]|inn[k])==inn[j]+inn[k])
                    {
                        dp[i][j]+=dp[i-1][k];
                        dp[i][j]%=MOD;
                    }
                }
            }
        }
        ll rem=0;
        for(i=0;inn[i]<=ma;i++)
        {
            rem+=dp[n][i];
        }
        rem%=MOD;
        printf("%I64d\n",rem);
    }
    return 0;
}

 




  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved