URAL 1519 Formula 1(插头DP)
2017-07-31 13:52
525 查看
1519. Formula 1
Time limit: 1.0 secondMemory 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 importantthing 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 technicaluniversity!.. 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 rectangle N*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. There are at least 4 cells without gopher
holes.
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 Source: Timus Top Coders: Third Challenge
题目大意:
给你一个n*m的矩阵,有些格子可以走,有些不能走,问有多少条哈密顿回路。
解题思路:
插头dp入门题,求解方法请看cdq的《基于连通性状态压缩的动态规划问题》。这里使用了最小表示法进行编码。
AC代码:
/*
*为了方便轮廓线的表示,矩阵下标从1开始
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <stack>
#include <deque>
#include <string>
#include <map>
#include <set>
#include <list>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define fi first
#define se second
#define mem(a,b) memset((a),(b),sizeof(a))
const int MAXN=12+2;
int N,M;
int ey,ex;//终点坐标
bool maze[MAXN][MAXN];//0表示不能走,1表示必须走
int tmp_state[MAXN];//保存临时轮廓线状态
int ch[MAXN];//最小表示法使用
struct HashMap
{
const static int mod=30007;//小一点
const static int maxn=1000100;//大概状态数大一些
int head[mod];//链表头指针
int next[maxn];//指向链表下一个节点
int size;//当前节点数
LL key[maxn],val[maxn];//键,值
void clear()
{
size=0;
memset(head,-1,sizeof head);
}
inline void insert(LL _key,LL _val)
{
int p=_key%mod;//取模后对应的链
for(int i=head[p];~i;i=next[i])
if(key[i]==_key)
{
val[i]+=_val;
return ;
}
key[size]=_key;
val[size]=_val;
next[size]=head[p];
head[p]=size++;
}
}hm[2];
void init()//初始化
{
ex=0;
mem(maze, 0);//要把边界全部置零
}
void decode(int *tmp_state, int M, LL key)//把数字解压到数组,M表示矩阵一行的长度
{
for(int i=M;i>=0;--i)//这里用3位表示一个插头的状态
{
tmp_state[i]=key&7;
key>>=3;
}
}
LL encode(int *tmp_state, int M)//最小表示法
{
int cnt=1;
mem(ch,-1);
ch[0]=0;
LL res=0;
for(int i=0;i<=M;++i)
{
if(ch[tmp_state[i]]==-1)
ch[tmp_state[i]]=cnt++;
tmp_state[i]=ch[tmp_state[i]];
res<<=3;
res|=tmp_state[i];
}
return res;
}
void dp_empty(int y, int x, bool now)//必须走的格子
{
for(int i=0;i<hm[now].size;++i)//枚举状态
{
decode(tmp_state, M, hm[now].key[i]);
int left=tmp_state[x-1], up=tmp_state[x];
if(left && up)
{
if(left==up)//最后一个非障碍格子,同一个连通分量合并
{
if(y==ey && x==ex)
{
tmp_state[x-1]=tmp_state[x]=0;
hm[!now].insert(encode(tmp_state, M-(x==M)), hm[now].val[i]);//处理完一行时,把竖着的轮廓线转移到下一行
}
}
else//不在一个强连通分量则合并
{
tmp_state[x-1]=tmp_state[x]=0;
for(int i=0;i<=M;++i)
if(tmp_state[i]==up)//第二个强连通分量的其它点的标记都修改
tmp_state[i]=left;
hm[!now].insert(encode(tmp_state, M-(x==M)), hm[now].val[i]);
}
}
else if((left && !up) || (!left && up))//把路径延伸
{
int t=left?left:up;
if(maze[y][x+1])
{
tmp_state[x-1]=0;
tmp_state[x]=t;
hm[!now].insert(encode(tmp_state, M), hm[now].val[i]);
}
if(maze[y+1][x])
{
tmp_state[x-1]=t;
tmp_state[x]=0;
hm[!now].insert(encode(tmp_state, M-(x==M)), hm[now].val[i]);
}
}
else//没有插头
{
if(maze[y][x+1] && maze[y+1][x])
{
tmp_state[x-1]=tmp_state[x]=13;
hm[!now].insert(encode(tmp_state, M), hm[now].val[i]);
}
}
}
}
void dp_block(int y, int x, bool now)//有障碍
{
for(int i=0;i<hm[now].size;++i)
{
decode(tmp_state, M, hm[now].key[i]);
hm[!now].insert(encode(tmp_state, M-(x==M)), hm[now].val[i]);
}
}
void solve()
{
bool now=0;
hm[now].clear();
hm[now].insert(0, 1);
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j)
{
hm[!now].clear();
if(maze[i][j])
dp_empty(i, j, now);
else dp_block(i, j, now);
now^=1;
}
LL ans=0;
for(int i=0;i<hm[now].size;++i)
ans+=hm[now].val[i];
printf("%lld\n",ans);
}
int main()
{
while(~scanf("%d%d", &N, &M))
{
init();
for(int i=1;i<=N;++i)
{
char s[MAXN];
scanf("%s",s+1);
for(int j=1;j<=M;++j)
if(s[j]=='.')
{
ey=i;
ex=j;
maze[i][j]=true;
}
}
if(!ex)//没有空格子
{
puts("0");
continue;
}
solve();
}
return 0;
}
相关文章推荐
- Ural1519 Formula 1 插头dp入门
- Ural 1519 Formula --插头DP
- Ural 1519 Formula 1 插头DP(单回路)
- URAL1519 Formula 1 【插头dp】
- Ural 1519 Formula 1 插头DP
- URAL - 1519 Formula 1 (插头DP)
- bzoj 1814: Ural 1519 Formula 1 插头dp经典题
- ural 1519 Formula 1(轮廓线|插头DP|括号配对)
- URAL1519 Formula 1(插头dp的基础题 ——详细解释)
- URAL 1519 Formula 1(插头DP,入门题)
- Ural 1519 Formula 1( 插头dp )
- ural 1519 Formula 1 插头dp 一条回路
- ural 1519 Formula 1(插头dp)
- HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)
- 【bzoj1814】Ural 1519 Formula 1 插头dp
- ural 1519 Formula 1(插头dp)
- URAL 1519 Formula 1 dp(插头)
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
- [ural1519]Formula 1 && 插头DP
- URAL 1519 Formula 1 【插头DP模板题】