【hiho一下 第九周】 状态压缩·二

【题目链接】:http://hihocoder.com/problemset/problem/1048

【题意】

【题解】

按从左到右然后从上到下的顺序;
依次枚举每个格子是竖条还是横条;
然后在搜索的时候保证前i-1行全都填满;
记录下这一行和下一行的状态就好了;
2*m个格子;m最大为5;
完全能用二进制数来表示;
写一个记忆化搜索就好;
dfs(int x,int y,int cur,int nex)
这里dp[x][y][cur][nex]表示当前处理的格子为x,y;然后当前行和下一行的格子占据状态为cur和nex的方案数;

【Number Of WA

0

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1100;
const int MOD = 1000000007;

int n,m,dp[N][8][33][33];

void add(int &a,int b)
{
    a+=b;
    if (a>=MOD) a-=MOD;
}

int dfs(int x,int y,int cur,int nex)
{
    if (x==n) return 1;
    if (dp[x][y][cur][nex]!=-1)
        return dp[x][y][cur][nex];
    if (cur&(1<<y))
    {
        if (y==m-1)
            return dp[x][y][cur][nex] = dfs(x+1,0,nex,0);
        else
            return dp[x][y][cur][nex] = dfs(x,y+1,cur,nex);
    }
    else
    {
        dp[x][y][cur][nex] = 0;
        if (y+1<=m-1 && !(cur&(1<<(y+1))))
            add(dp[x][y][cur][nex],dfs(x,y,cur|(1<<y)|(1<<(y+1)),nex));
        if (x+1<=n-1 && !(nex&(1<<y)))
            add(dp[x][y][cur][nex],dfs(x,y,cur|(1<<y),nex|(1<<y)));
    }
    return dp[x][y][cur][nex];
}

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf not use
    ms(dp,255);
    cin >> n >> m;
    cout << dfs(0,0,0,0);
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626352.html