URAL - 1519 Formula 1
阿新 • • 發佈:2018-11-02
題面
題意
給出一張網格圖,用一條哈密頓迴路覆蓋它的所有格子,問有幾種方案。
做法
這道題與HDU - 1693 Eat the Trees的區別在於此題只有一條迴路,因此dp方法有所不同。
同樣是插頭dp,可以發現對於每一條合法的迴路,沿輪廓線將其切成兩部分後,輪廓線上面的部分是多個聯通塊,且每個聯通塊與輪廓線恰好有兩個交點,可以用括號序列來維護這兩個交點,然後逐格遞推時分情況轉移即可,但因為狀態總數為
,所以在轉移時只要記錄方案數非零的狀態轉移即可
程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define N 15
#define M 1600000
using namespace std;
ll m,n,dp[2][M],san[N],li,lj,ans;
char str[N];
bool mm[N][N],in[M],now,cur;
vector<ll>have[2];
inline ll get(ll u,ll v){return u/san[v-1]%3;}
inline ll chg(ll u,ll v,ll w){return u+(w-get(u,v))*san[v-1];}
inline void add(ll u,ll v)
{
if(!dp[now][u]) have[now].push_back(u);
dp[now][u]+=v;
}
int main()
{
ll i,j,k,kk,t,l,p,q,jb;
cin>>m>>n;
san[0]=1;
for(i=1;i<=n+1;i++) san[i]=san[i-1]*3;
for(i=1;i<=m;i++)
{
scanf("%s",str+1);
for(j=1;j<=n;j++)
{
if(str[j]=='*') mm[i][j]=1;
else li=i,lj=j;
}
mm[i][0]=mm[i][n+1]=1;
}
for(i=0;i<=n+1;i++) mm[0][i]=mm[m+1][i]=1;
now=1;
add(0,1);
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
swap(now,cur);
have[now].clear();
for(kk=0;kk<have[cur].size();kk++)
{
k=have[cur][kk];
p=get(k,j),q=get(k,j+1);
if(mm[i][j])
{
if(!p&&!q) add(k,dp[cur][k]);
}
else if(!p&&!q)
{
if(!mm[i+1][j] && !mm[i][j+1])
{
t=chg(k,j,1),t=chg(t,j+1,2);
add(t,dp[cur][k]);
}
}
else if(!p||!q)
{
t=chg(k,j,0),t=chg(t,j+1,0);
if(!mm[i][j+1]) add(chg(t,j+1,p+q),dp[cur][k]);
if(!mm[i+1][j]) add(chg(t,j,p+q),dp[cur][k]);
}
else if(p==2&&q==1)
{
t=chg(k,j,0),t=chg(t,j+1,0);
add(t,dp[cur][k]);
}
else if(p==1&&q==1)
{
t=chg(k,j,0),t=chg(t,j+1,0),jb=0;
for(l=j+2;;l++)
{
if(get(k,l)==1) jb++;
else if(jb&&get(k,l)==2) jb--;
else if(!jb&&get(k,l)==2) break;
}
t=chg(t,l,1);
add(t,dp[cur][k]);
}
else if(p==2&&q==2)
{
t=chg(k,j,0),t=chg(t,j+1,0),jb=0;
for(l=j-1;;l--)
{
if(get(k,l)==2) jb++;
else if(jb&&get(k,l)==1) jb--;
else if(!jb&&get(k,l)==1) break;
}
t=chg(t,l,2);
add(t,dp[cur][k]);
}
else if(i==li&&j==lj) ans+=dp[cur][k];
dp[cur][k]=0;
}
}
swap(now,cur);
have[now].clear();
for(kk=0;kk<have[cur].size();kk++)
{
k=have[cur][kk];
add(k*3,dp[cur][k]);
dp[cur][k]=0;
}
}
cout<<ans;
}