
正文
[BZOJ]|[Ural] Formula 1-----插头DP入门
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
1519. Formula 1Time limit: 1.0 second
Memory limit: 64 MBBackground
Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely, for such an important thing a new race circuit should be built as well as hotels, restaurants, international airport - everything for Formula 1 fans, who will flood the city soon. But when all the hotels and a half of the restaurants were built, it appeared, that at the site for the future circuit a lot of gophers lived in their holes. Since we like animals very much, ecologists will never allow to build the race circuit over the holes. So now the mayor is sitting sadly in his office and looking at the map of the circuit with all the holes plotted on it.Problem
Who will be smart enough to draw a plan of the circuit and keep the city from inevitable disgrace? Of course, only true professionals - battle-hardened programmers from the first team of local technical university!.. But our heroes were not looking for easy life and set much more difficult problem: "Certainly, our mayor will be glad, if we find how many ways of building the circuit are there!" - they said.It should be said, that the circuit in Vologda is going to be rather simple. It will be a rectangleN*M cells in size with a single circuit segment built through each cell. Each segment should be parallel to one of rectangle's sides, so only right-angled bends may be on the circuit. At the picture below two samples are given for N = M = 4 (gray squares mean gopher holes, and the bold black line means the race circuit). There are no other ways to build the circuit here.
Input
The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.Output
You should output the desired number of ways. It is guaranteed, that it does not exceed 263-1.Samples
input output 4 4
**..
....
....
....
2
4 4
....
....
....
....
6
Problem Author: Nikita Rybak, Ilya Grebnov, Dmitry Kovalioff
Problem Source: Timus Top Coders: Third Challenge
Memory limit: 64 MB
Background
Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic games of 20**, it is well-known, that the city will conduct one of the Formula 1 events. Surely, for such an important thing a new race circuit should be built as well as hotels, restaurants, international airport - everything for Formula 1 fans, who will flood the city soon. But when all the hotels and a half of the restaurants were built, it appeared, that at the site for the future circuit a lot of gophers lived in their holes. Since we like animals very much, ecologists will never allow to build the race circuit over the holes. So now the mayor is sitting sadly in his office and looking at the map of the circuit with all the holes plotted on it.
Problem
Who will be smart enough to draw a plan of the circuit and keep the city from inevitable disgrace? Of course, only true professionals - battle-hardened programmers from the first team of local technical university!.. But our heroes were not looking for easy life and set much more difficult problem: "Certainly, our mayor will be glad, if we find how many ways of building the circuit are there!" - they said.
It should be said, that the circuit in Vologda is going to be rather simple. It will be a rectangleN*M cells in size with a single circuit segment built through each cell. Each segment should be parallel to one of rectangle's sides, so only right-angled bends may be on the circuit. At the picture below two samples are given for N = M = 4 (gray squares mean gopher holes, and the bold black line means the race circuit). There are no other ways to build the circuit here.

Input
The first line contains the integer numbers N and M (2 ≤ N, M ≤ 12). Each of the next N lines contains M characters, which are the corresponding cells of the rectangle. Character "." (full stop) means a cell, where a segment of the race circuit should be built, and character "*" (asterisk) - a cell, where a gopher hole is located.
Output
You should output the desired number of ways. It is guaranteed, that it does not exceed 263-1.
Samples
| input | output |
|---|---|
4 4 | 2 |
4 4 | 6 |
Problem Author: Nikita Rybak, Ilya Grebnov, Dmitry Kovalioff
Problem Source: Timus Top Coders: Third Challenge
Problem Source: Timus Top Coders: Third Challenge
Tags: none (hide tags for unsolved problems)
Difficulty: 426 Printable version Submit solution Discussion (29)
My submissions All submissions (10084) All accepted submissions (3166) Solutions rating (868)
My submissions All submissions (10084) All accepted submissions (3166) Solutions rating (868)
题意:给出n*m的棋盘,有一些格子有障碍,求有多少个不经过障碍的哈密顿回路。
考虑:
1.搜索?
,当然优化也过不了。
,当然优化也过不了。2.状压DP?考虑维护每一行哪些格子是在之前就连通的
,预处理可行转移
,再优化预处理状态
,还是过不了。
,预处理可行转移
,再优化预处理状态
,还是过不了。3.这时候想到轮廓线DP。
设
表示转移完
,轮廓线上从左到右n+1个插头是否存在以及它们的连通性为S的方案总数。再想如何表示S,即最小表示法
表示转移完
,轮廓线上从左到右n+1个插头是否存在以及它们的连通性为S的方案总数。再想如何表示S,即最小表示法
时合法的状态数总数为1333113个,可以解决本题。
4.可以发现轮廓线以上的路径一定互不相交,并且两两匹配,所以可以用括号序列来表示状态,0表示左括号"(",1表示右括号”)",括号的意义即使到轮廓线上的路径是出路径还是入路径。

可以发现,一行有m个格子,但是却有m+1个状态,因为在转移的时候我们要考虑到,当前处理的格子的右边的情况(绿色箭头)
每一次转移之后相当于是轮廓线上当前决策格子的左插头改成下插头,上插头改成右插头的状态。
每一次转移之后改变的是对应格子轮廓线上连通的状态,我们只关心当前格子轮廓线以上的连线终止与轮廓线上(由于要形成哈密顿回路,所以不存在自环)的情况,而并不在意轮廓线之下的连线方式。
那么分情况考虑转移(把橘色的称为左插头,绿色的称为上插头)

(1)上,左插头都没有,而且当前格子(x,y),(x+1,y),(x,y+1)均不为障碍,则可以新建一个连通块。
...00... --------> ...12...
(2)仅有有上插头,或仅有下插头,延续原来的连通分量即可。
...10... --------> ...12...
(3)上下插头都有。
3.1,上下插头均为出路径,画图可知即使两个连通分量左边合并,需要找到相应状态最左边那个右括号将其修改为左括号。
.........2... -------> .........2
3.2,左插头为入路径,上插头为出路径,即直接将对应状态位置上的左右括号消去即可。
...12... ------> ...00...
3.3,做插头为出路径,右插头为入路径,这个情况下就是答案的状态了,而且只能出现在最右下角的那个格子(其余的不合法)。
细节
注意题目的空间,以及还可以加上的优化。
我们把每一次的状态hash起来(而不是动态存储)
一种数据 :
1
.
三进制存储?为了方便,我们采用4进制(位运算中两位来表示一位)
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
#define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
#define CC(a,b) memset(a,b,sizeof(a));
#define u64 unsigned long long
#define llg long long
const int sz=;
llg n,m,state[][sz],tail,hash[sz],bit[],tot[],nn,mm,k=;
u64 dp[][sz],ans; char mp[][]; llg init()
{
llg cs=;
CC(mp,);
CC(dp,);
tot[]=dp[][]=;
state[][]=;
ans=k=; char ch;
for (llg i=;i<=n;i++)
{
scanf("%c",&ch);
for (llg j=;j<=m;j++)
{
scanf("%c",&ch);
mp[i][j]=ch=='.';
if (ch=='.') cs++;
if (mp[i][j]) nn=i,mm=j;
}
}
return cs;
} void in(llg s,u64 sum)
{
llg p=s%sz;
while (hash[p])
{
if (state[k][hash[p]]==s)
{
dp[k][hash[p]]+=sum;
return ;
}
p++;
if (p==sz) p=;
}
hash[p]=++tot[k];
state[k][hash[p]]=s;
dp[k][hash[p]]=sum;
} void work()
{
for (llg i=;i<=n;i++)
{
for (llg j=;j<=m;j++)
{
k^=;
CC(hash,);
tot[k]=;
for (llg u=;u<=tot[-k];u++)
{
llg s=state[-k][u],p=(s>>bit[j-])&,q=(s>>bit[j])&;
u64 sum=dp[-k][u];
if (!mp[i][j])
{
if (!q && !p) in(s,sum);
}
else
{
if (!p && !q)
{
if (!mp[i][j+] || !mp[i+][j]) continue;
s=s^(<<bit[j-])^(<<bit[j]<<);
in(s,sum);
}
else
if (!p && q)
{
if (mp[i][j+]) in(s,sum);
if (mp[i+][j]) s=s^q*(<<bit[j-])^q*(<<bit[j]),in(s,sum);
}
else
if (p && !q)
{
if (mp[i+][j]) in(s,sum);
if (mp[i][j+]) s=s^p*(<<bit[j-])^p*(<<bit[j]),in(s,sum);
}
else
if (p+q==)
{
llg nd=;
for (llg u=j+;j<=m;u++)
{
llg w=(s>>bit[u])&;
if (w==) nd++;
if (w==) nd--;
if (!nd) {s-=(<<bit[u]); break;}
}
s=s^(<<bit[j])^(<<bit[j-]),in(s,sum);
}
else
if (p+q==)
{
llg nd=;
for (llg u=j-;u>=;--u)
{
llg w=(s>>bit[u])&;
if (w==) nd++;
if (w==) nd--;
if (!nd) {s+=(<<bit[u]); break;}
}
s=s^(<<bit[j]<<)^(<<bit[j-]<<);
in(s,sum);
}
else
if (p== && q==)
{
if (i==nn && j==mm) ans+=sum;
}
else
if (p== && q==)
{
s=s^(<<bit[j-]<<)^(<<bit[j]);
in(s,sum);
} }
}
}
for (llg j=;j<=tot[k];j++) state[k][j]<<=;
}
cout<<ans<<endl;
} int main()
{
//yyj("a");
for (llg i=;i<=;i++) bit[i]=(i<<);
while (scanf("%lld%lld",&n,&m)!=EOF)
{
if (init()%) {cout<<""<<endl; continue;}
work();
}
return ;
}
参考:《基于连通性状态压缩的动态规划问题_Cdq》》--陈丹琦
博客:http://www.cnblogs.com/Tunix/p/4312203.html







