真-插头DP模板题,也是用插头DP的思想做的,括号表示法耗时比最小表示法略少,但是思路复杂小小,代码好难打啊,弄了很久才AC。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
using namespace std;
#define inf 0x7fffffff
#define N 600007
#define LL long long
LL str[20];
LL maps[20][20],n,m;
LL ex,ey;
struct hashmap
{
LL visit[N],next[N];
LL h[N];
LL num[N],cnt;
void clear()
{
cnt = 0;
memset(visit,-1,sizeof(visit));
}
void insert(LL x,LL y)
{
LL z = x%N;
for(LL i = visit[z];i != -1;i = next[i])
{
if(h[i] == x)
{
num[i] += y;
return ;
}
}
next[cnt] = visit[z];
num[cnt] = y;
h[cnt] = x;
visit[z] = cnt++;
return ;
}
}s[2];
void change(LL x,LL len) //数字变数组
{
LL mark = 3;
for(LL i = 0;i <= len;i++)
{
str[i] = x&mark;
x >>= 2;
}
}
LL changeover(LL len) //数组转数字
{
LL ans = 0;
for(LL i = len;i >= 0;i--)
{
ans <<= 2;
ans |= str[i];
}
return ans;
}
void get(LL len) //换行
{
for(LL i = len;i >= 1;i--)
{
str[i] = str[i - 1];
}
str[0] = 0;
}
LL fin(LL len,LL a) //寻找匹配括号
{
LL i,j;
LL x;
if(str[a] == 1)
{
for(i = a + 1,j = 0;i <= len;i++)
{
if(str[i] == 1)
j++;
if(str[i] == 2)
{
if(j == 0)
{
x = i;
break;
}
else
j--;
}
}
}
else
{
for(i = a - 1,j = 0;i >= 0;i--)
{
if(str[i] == 2)
j++;
if(str[i] == 1)
{
if(j == 0)
{
x = i;
break;
}
else
j--;
}
}
}
return x;
}
void adjust(LL len,LL a,LL b) //调整括号匹配
{
LL x = fin(len,a),y = fin(len,b);
if(x < y)
{
str[x] = 1;
str[y] = 2;
}
else
{
str[x] = 2;
str[y] = 1;
}
}
void dp(LL last,LL nxt,LL i,LL j,LL k)
{
change(s[last].h[k],m);
if(str[j] && str[j + 1] )
{
if(maps[i][j + 1])
return ;
if(str[j] == 1 && str[j + 1] == 2)
{
if(i == ex && j + 1 == ey)
{
str[j] = str[j + 1] = 0;
if(j == m - 1)
get(m);
s[nxt].insert(changeover(m),s[last].num[k]);
}
else return ;
}
else
{
adjust(m,j,j + 1);
str[j] = str[j + 1] = 0;
if(j == m - 1)
get(m);
s[nxt].insert(changeover(m),s[last].num[k]);
}
}
else if(str[j] || str[j + 1])
{
if(maps[i][j + 1] == 1)
return ;
LL t = max(str[j],str[j + 1]);
str[j] = t;
str[j + 1] = 0;
if(j == m - 1)
{
get(m);
s[nxt].insert(changeover(m),s[last].num[k]);
}
else
{
s[nxt].insert(changeover(m),s[last].num[k]);
str[j] = 0;
str[j + 1] = t;
s[nxt].insert(changeover(m),s[last].num[k]);
}
}
else
{
if(maps[i][j + 1] == 1)
{
if(j == m - 1)
{
get(m);
}
s[nxt].insert(changeover(m),s[last].num[k]);
}
else
{
if(j == m - 1)
return ;
str[j] = 1;str[j + 1] = 2;
s[nxt].insert(changeover(m),s[last].num[k]);
}
}
}
LL solve()
{
if(ex + ey == -2)
return 0;
LL i,j,k,l,flag = 0,nxt;
s[flag].clear();
s[flag].insert(0,1);
for(i = 1;i <= n;i++)
{
for(j = 0;j < m;j++)
{
nxt = flag^1;
s[nxt].clear();
for(k = 0;k < s[flag].cnt;k++)
{
dp(flag,nxt,i,j,k);
}
flag ^= 1;
}
}
for(i = 0;i < s[nxt].cnt;i++)
{
if(s[nxt].h[i] == 0)
return s[nxt].num[i];
}
return 0;
}
int main()
{
while(cin>>n>>m)
{
ex = ey = -1;
char x;
for(LL i = 1;i <= n;i++)
{
for(LL j = 1;j <= m;j++)
{
cin>>x;
if(x == '*')
{
maps[i][j] = 1;
}
else
{
ex = i;
ey = j;
maps[i][j] = 0;
}
}
}
cout<<solve()<<endl;
}
return 0;
}