现在只会做基于棋盘上的简单路径和简单回路问题, 非棋盘上的问题,和广义路径,很费劲,等学完树的分治和树链剖分、Dance Links,有余力在研究它。
HDU 4285 | circuits |
贴一份模板,便于以后复习。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL ;
const LL MOD = 1000000007LL ;
const int HASH = 99997 ;
const int STATE = 10001000 ;
int N, M ,K, cur ,num, tot ; // 已有环的个数
int code[20] , ch[20] , g[20][20] ;
void init() {
char buf[20] ;
tot = 0 ;
memset(g ,0 ,sizeof(g)) ;
for(int i=1; i<=N; i++) {
scanf("%s" , buf + 1) ;
for(int j=1; j<=M ;j++) {
if(buf[j] == '.') g[i][j] = 1 ,tot++ ;
else g[i][j] = 0 ;
}
}
}
LL encode(){
memset(ch ,-1 ,sizeof(ch)) ;
ch[0] = 0;
LL ret = 0 , cnt = 1 ;
for(int i=0; i<=M; i++) {
if(ch[code[i]] == -1) ch[code[i]] = cnt++ ;
ret = ret <<3 | ch[code[i]] ;
}
ret = ret<<6 | num ;
return ret ;
}
void decode(LL s) {
num = s&63 ;
s>>=6 ;
for(int i=M; i>=0; i--) {
code[i] = s & 7 ;
s >>= 3 ;
}
}
void trans(int u,int v) {
for(int i=0; i<=M; i++) if(code[i] == u) code[i] = v ;
}
struct Hash{
int head[HASH] , next[STATE] , sz;
LL f[STATE] , sta[STATE] ;
void init() {
sz = 0 ; memset(head, -1 ,sizeof(head)) ;
}
void push(LL s , LL val){
int u = s % HASH ;
for(int i=head[u] ; ~i ; i=next[i]) {
if(sta[i] == s ) {
f[i] += val ;
while(f[i] >= MOD) f[i] -= MOD ;
return ;
}
}
sta[sz] = s , f[sz] = val , next[sz] = head[u] , head[u] = sz ++ ;
}
}dp[2];
void update(int j , LL s , LL val){
int _num = s & 63 ;
if(j == M) s = ( (s>>3)&(~63) ) | _num ;
dp[cur^1].push(s , val) ;
}
void dpblock(int i,int j){
for(int k=0; k<dp[cur].sz; k++){
update(j , dp[cur].sta[k] , dp[cur].f[k]) ;
}
}
bool check(int p , int q) {
int cnt = 0 ;
for(int i=0; i<=p; i++) if(code[i]) {
for(int j=q; j<=M; j++) if(code[j]) {
if(code[i] == code[j]) cnt ++ ;
}
}
return cnt % 2 == 0 ;
}
void dpblank(int i,int j) {
for(int k=0; k<dp[cur].sz; k++){
decode(dp[cur].sta[k]) ;
int &P = code[j-1] , &Q = code[j] ;
if(P && Q){
if(P==Q){
if(num < K && check(j-2 , j+1)) {
P = Q = 0 ;
num++ ;
update(j , encode() , dp[cur].f[k]) ;
}
}
else{
trans(P , Q) ;
P = Q = 0 ;
update(j , encode() ,dp[cur].f[k]) ;
}
}
else if(P) {
if(g[i+1][j]) update(j , dp[cur].sta[k] , dp[cur].f[k]) ;
if(g[i][j+1]) {
Q = P , P = 0;
update(j , encode() , dp[cur].f[k]) ;
}
}
else if(Q) {
if(g[i][j+1]) update(j, dp[cur].sta[k] , dp[cur].f[k]) ;
if(g[i+1][j]) {
P = Q , Q = 0 ;
update( j , encode() , dp[cur].f[k]);
}
}
else {
if(g[i][j+1] && g[i+1][j]) {
P = Q = M + 2 ;
update(j , encode() ,dp[cur].f[k]) ;
}
}
}
}
int main()
{
int T ;
scanf("%d" ,&T) ;
while(T--) {
scanf("%d%d%d", &N, &M ,&K) ;
init() ;
if(tot/4 < K || K==0) {
puts("0") ;
continue ;
}
cur = 0;
dp[cur].init() ;
dp[cur].push(0 , 1) ;
for(int i=1; i<=N; i++){
for(int j=1; j<=M; j++) {
dp[cur^1].init() ;
if(g[i][j]) dpblank(i ,j );
else dpblock(i , j) ;
cur^=1 ;
}
}
LL ans = 0;
for(int k=0; k<dp[cur].sz; k++) {
if( (dp[cur].sta[k] & 63) == K) ans += dp[cur].f[k] ;
}
while(ans >= MOD) ans -= MOD ;
printf("%I64d\n" , ans) ;
}
return 0;
}