男人八题之一
本来是要用到独立插头的,但是这道题可以转化,
这样做就可以不求哈密顿路径数量,而求哈密顿回路数量,要简单得多。陈丹琦神牛的文章里介绍的方法。
然后就和Formula 1一模一样了。
因为n要增大4,m要增大2,所以我一开始map[10][10]小了。
然后又没有用long long。还有map没有初始化,调了很久很久。核心是没有问题的。
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <algorithm>
typedef long long ll;
const long maxs = 1000000;
const long Hmod = 12346;
long cnt[2];
ll f[2][maxs];
long Sta[2][maxs];
char map[15][15];
long ths = 0;
long pre = 1;
long n;long m;
struct node
{
long ind;
long sta;
node* nxt;
};
node tmp[maxs];
node* hash[Hmod];
inline int getint()
{
char tmp;bool sgn=1;long rs=0;
do tmp = getchar();
while (!isdigit(tmp) && tmp-'-');
if (tmp == '-'){tmp=getchar();sgn=0;}
do rs = (rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
void clear()
{
cnt[ths] = 0;
memset(hash,0,sizeof(hash));
}
long get_brac(long s,long p,long d)
{
long _cnt = 0;
for (long i=p;i<(m<<1)+1 && i>-1;i+=d)
{
if (((s >> i)& 3) == 1) _cnt ++;
if (((s >> i)& 3) == 2) _cnt --;
if (!_cnt) return i;
}
return -100000;
}
void insert(long S)///
{
long h = S%Hmod;
++cnt[ths];
tmp[cnt[ths]].ind = cnt[ths];
tmp[cnt[ths]].sta = S;
tmp[cnt[ths]].nxt = hash[h];
hash[h] = &tmp[cnt[ths]];
}
long getID(long S)
{
long h = S%Hmod;
node* now = hash[h];
while (now && now->sta != S)
now = now->nxt;
if (!now)
{
insert(S);
f[ths][cnt[ths]] = 0;
Sta[ths][cnt[ths]] = S;
return cnt[ths];
}
return now->ind;
}
void work()
{
ths = 0;pre = 1;
cnt[ths] = cnt[pre] = 0;
memset(hash,0,sizeof hash);
f[ths][getID(0)] = 1;
for (long i=1;i<n+1;i++)
{
for (long j=1;j<m+1;j++)
{
ths ^= pre;pre ^= ths;ths ^= pre;
clear();
long q = (m-j)<<1;
long p = q+2;
for (long k=1;k<cnt[pre]+1;k++)
{
long last = Sta[pre][k];
if (j == 1)
{
if (last & 3)continue;
else last >>= 2;
}
long pn = ((last>>p)&3);
long qn = ((last>>q)&3);
long now = last - (pn<<p) - (qn<<q);
if (!map[i][j])
{
if (!pn && !qn)
f[ths][getID(now)] += f[pre][k];
continue;
}
if (!pn && !qn)
{
f[ths][getID(now|(1<<p)|(2<<q))] += f[pre][k];
continue;
}
if (!pn || !qn)
{
f[ths][getID(last)] += f[pre][k];
f[ths][getID(now|(pn<<q)|(qn<<p))] += f[pre][k];
continue;
}
if (pn == 1 && qn == 1)
{
f[ths][getID(now ^ (3<<get_brac(last,q,-2)))] += f[pre][k];
continue;
}
if (pn == 1 && qn == 2)
{
bool ok = true;
for (long j1=j+1;j1<m+1;j1++)
{
if (map[i][j1])
{
ok = false;
break;
}
}
if (ok)
for (long i1=i+1;i1<n+1;i1++)
for (long j1=1;j1<m+1;j1++)
{
if (map[i1][j1])
{
ok = false;
break;
}
}
if (ok)
f[ths][getID(now)] += f[pre][k];
continue;
}
if (pn == 2 && qn == 1)
{
f[ths][getID(now)] += f[pre][k];
continue;
}
if (pn == 2 && qn == 2)
{
f[ths][getID(now ^ (3<<get_brac(last,p,2)))] += f[pre][k];
continue;
}
}
}
}
std::cout << f[ths][getID(0)] << std::endl;
}
int main()
{
freopen("tour.in","r",stdin);
freopen("tour.out","w",stdout);
while (1)
{
n = getint();m = getint();
if (n == 0 && m == 0) break;
for (long i=1;i<n+1;i++)
for (long j=1;j<m+1;j++)
{
char tmp;
do tmp = getchar();
while (tmp-'#'&&tmp-'.');
map[i+2][j+2] = tmp=='#'?0:1;
}
if (m < 2) {printf("1\n");continue;}
for (long i=1;i<n+3;i++)
{
map[i][2] = map[i][m+3] = 0;
map[i][1] = map[i][m+4] = 1;
}
for (long j=2;j<m+4;j++)
{
map[2][j] = 0;
map[1][j] = 1;
}
map[n+2][2] = map[n+2][m+3] = 1;
n += 2;m += 4;
work();
}
return 0;
}