原题:HDU4285
题意:N*M有障碍矩阵,“*”为障碍,求用多个回路覆盖所有非障碍点,要求回路之间不能嵌套,求回路数为K的方案数(1 <= n,m <=12)。
解:
插头dp
相比耿直的多回路问题,这题多了两个要求,一是k个回路,二是回路之间不能嵌套。
对于第一个要求,显然,在储存当前轮廓线的插头状态时,还要储存已产生的回路数,最大为K,因为回路至少4格,所以K最大值为12*12/4 = 36,需要6位二进制(写的时候智障地用了8位,影响不大)。
对于第二个要求,在每个状态转移的时候,若轮廓线前面的插头数为奇数,则意味着会产生嵌套,为非法情况。
(1).障碍点
只有没有左,上插头的状态,转移到没有右,下插头的状态
(2).非障碍点
- 有左,上插头:如果左,上插头连通,合并左上插头,并且要满足条件2使得轮廓线上该列以前的插头数为偶数,如果左,上插头不连通,合并左上插头,并将轮廓线上的上插头连通块加入到左插头连通块中。
- 只有左插头或者只有上插头:延续插头的连通性,转移到只有右插头或只有下插头的状态。
- 没有左,上插头:新建连通块,有右,下插头,标号为八进制中的7。
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>
using namespace std;
#define N 15
#define inf 0x7f7f7f7f
#define mod 1000000007
#define HASH 10007
#define STATE 1000100
typedef long long ll;
int n, m, l;
int code[N], ch[N];
int mp[N][N];
struct HASHMAP
{
int head[HASH], next[STATE], size;
ll f[STATE], state[STATE];
void init() {
size = 0;
memset(head, -1, sizeof(head));
}
void push(ll st, ll ans) {
int h = st % HASH;
for (