[설명] 밭

압력 시리즈 II처럼.

주제 링크

타이틀 효과 : 주어진 \ (n 개 * m 개의 \) , 일부는 수없는 위치의 일부를 넣을 수 행렬. 그리드의 규정은 왼쪽을 넣고 바로 내려 놓고 수 없습니다. 얼마나 많은 그리드 프로그램을 넣어 물었다.

고려 \을 (N, m의 \)의 압력의 형상이기 때문에, 작다.

감압 같은 표현 있다면, 우리는 각 광고 넣어 \을 (01 \) 행렬 이진 압입, 상기 라인의 상태를 나타낸다.

우리가 압력 라인을 완료 한 후 그래서 분명히 \ (n \) 수는 각 라인의 상태를 나타냅니다. 즉, 상태들의 총 수이다 (\ 상기 n ^ 2 \) .

또한, 때문에 바로 넣어 그것을 처리하기 위해, 먼저 같은 법적 지위를 둘 수 없습니다.

고려해야 할 계속 \ (DP \) 가.

각 상태를 열거하는 각 행 (압축 상태)를 통해 무엇이이 상태에 대응할 수있다 그 다음 라인의 상태에 대응할 수있다. 우리는 합법적 인 프로그램 부울 배열을 경험 앞에 넣을 수 있습니다.

그래서 우리는 먼저 합법적 인 상태를 선택해야합니다. 둘째,이 상태는 제목에 심어 지역의지도를 제공 할 수 없습니다. 우리는 사용할 수 있습니다 \ (J & MP [I] == J의 \)를 법적할지 여부를 결정합니다.

그럼 다음 줄의 상태를 열거합니다. 물론 위 아래로 인접한 두 행이없는 \을 (1 \) \ (J & k의 \)가 될 수있다.

그런 다음이 축적 된 상태가 좋아한다.

주제 다. , 그들이 할 수있는 그 왼쪽과 오른쪽 판단을 참고 :

$ & I (I << 1) == 0 $ \ (&& \) \ (I & (I >> 1) == 0 \)

우선 순위를 참고 습관 괄호.

\(암호:\)

#include<iostream>
using namespace std;
int n,m,a[20][20],mp[20];
int dp[20][5000],Ans;
bool state[5000];
const int Hws=100000000;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            scanf("%d",&a[i][j]);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            mp[i]=(mp[i]<<1)+a[i][j];
    for(int i=0;i<(1<<m);++i)if(((i&(i<<1))==0)&&((i&(i>>1)))==0)state[i]=1;
    dp[0][0]=1;
    for(int i=1;i<=n;++i){
        for(int j=0;j<(1<<m);++j)
            if(state[j]&&((j&mp[i])==j)){
                for(int k=0;k<(1<<m);++k)
                    if((k&j)==0){
                        dp[i][j]+=dp[i-1][k];
                        dp[i][j]%=Hws;
                    }
            }
    }
    for(int i=0;i<(1<<m);++i)Ans+=dp[n][i],Ans%=Hws;
    printf("%d\n",Ans);
    return 0;
}

추천

출처www.cnblogs.com/h-lka/p/11402173.html