1814: Ural 1519 Formula 1

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 924  Solved: 351
[Submit][Status][Discuss]

Description

 一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数

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 2^63-1.

Sample Input

4 4
**..
....
....
....

Sample Output

2
分析:今天把插头dp学了一下,没想到dp还能写这么长......细节什么的也很多,在这里当一个模板吧.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std;
typedef long long ll; const int maxn = ;
const int pow[] = {,,,,,,,,,,,,};
int n,m,now,pre,tx,ty;
char map[][]; struct node
{
int head[maxn],nextt[maxn],tot;
ll sum[maxn],sta[maxn];
void clear()
{
memset(head,-,sizeof(head));
tot = ;
}
void push(ll x,ll v)
{
ll hashh = x % maxn;
for (int i = head[hashh]; i >= ; i = nextt[i])
{
if (sta[i] == x)
{
sum[i] += v;
return;
}
}
sta[tot] = x;
sum[tot] = v;
nextt[tot] = head[hashh];
head[hashh] = tot++;
}
} f[]; int turnleft(ll x,int k)
{
return x << pow[k];
} int get(ll x,int k)
{
return (x >> pow[k]) & ;
} ll del(ll x,int i,int j)
{
return x & (~( << pow[i])) & (~( << pow[j]));
} int findr(ll x,int pos)
{
int cnt = ;
for (int i = pos + ; i <= m; i++)
{
int k = get(x,i);
if (k == )
cnt++;
else if (k == )
cnt--;
if (!cnt)
return i;
}
} int findl(ll x,int pos)
{
int cnt = ;
for (int i = pos - ; i >= ; i--)
{
int k = get(x,i);
if (k == )
cnt++;
else if (k == )
cnt--;
if (!cnt)
return i;
}
} void solve2(int x,int y,int k)
{
int p = get(f[pre].sta[k],y - ); //右插头
int q = get(f[pre].sta[k],y); //下插头
ll staa = del(f[pre].sta[k],y - ,y); //将这两个插头删掉以后的状态
ll v = f[pre].sum[k];
if (!p && !q) //新建一个连通分量
{
if (map[x][y] == '*')
{
f[now].push(staa,v);
return;
}
if (x < n && y < n && map[x + ][y] == '.' && map[x][y + ] == '.')
f[now].push(staa | turnleft(,y - ) | turnleft(,y),v);
}
else if (!p || !q) //保持原来的连通分量
{
int temp = p + q;
if (x < n && map[x + ][y] == '.')
f[now].push(staa | turnleft(temp,y - ),v);
if (y < m && map[x][y + ] == '.')
f[now].push(staa | turnleft(temp,y),v);
}
else if (p == && q == ) //连接两个联通分量
f[now].push(staa ^ turnleft(,findr(staa,y)),v); //这里的异或实际上就是把1变成2,2变成1
else if (p == && q == )
f[now].push(staa ^ turnleft(,findl(staa,y - )),v);
else if (p == && q == )
f[now].push(staa,v);
else if (x == tx && y == ty)
f[now].push(staa,v);
} ll solve()
{
f[].clear();
f[].push(,);
now = ,pre = ; //滚动数组
for (int i = ; i <= n; i++)
{
pre = now;
now ^= ;
f[now].clear();
for (int k = ; k < f[pre].tot; k++)
f[now].push(turnleft(f[pre].sta[k],),f[pre].sum[k]); //左移一位,因为轮廓线下来的时候会少一个插头
for (int j = ; j <= m; j++)
{
pre = now;
now ^= ;
f[now].clear();
for (int k = ; k < f[pre].tot; k++)
solve2(i,j,k); //处理第k个状态
}
}
for (int i = ; i < f[now].tot; i++)
if (f[now].sta[i] == ) //没有插头了.
return f[now].sum[i];
return ;
} int main()
{
scanf("%d%d",&n,&m);
for(int i = ; i <= n; i++)
scanf("%s",map[i] + );
for (int i = ; i <= n; i++)
for (int j = ; j <= m; j++)
if (map[i][j] == '.')
tx = i,ty = j; //找右下角的非障碍点
if (!tx)
puts("");
else
printf("%lld\n",solve()); return ;
}

bzoj1814 Ural 1519 Formula 1(插头dp模板题)的更多相关文章

  1. BZOJ1814: Ural 1519 Formula 1(插头Dp)

    Description Regardless of the fact, that Vologda could not get rights to hold the Winter Olympic gam ...

  2. bzoj 1814: Ural 1519 Formula 1 插头dp经典题

    用的括号序列,听说比较快. 然并不会预处理,只会每回暴力找匹配的括号. #include<iostream> #include<cstdio> #include<cstr ...

  3. 【BZOJ1814】Ural 1519 Formula 1 插头DP

    [BZOJ1814]Ural 1519 Formula 1 题意:一个 m * n 的棋盘,有的格子存在障碍,求经过所有非障碍格子的哈密顿回路个数.(n,m<=12) 题解:插头DP板子题,刷板 ...

  4. bzoj 1814 Ural 1519 Formula 1 插头DP

    1814: Ural 1519 Formula 1 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 942  Solved: 356[Submit][Sta ...

  5. Ural 1519 Formula 1 插头DP

    这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...

  6. bzoj 1814 Ural 1519 Formula 1 ——插头DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1814 普通的插头 DP .但是调了很久.注意如果合并两个 1 的话,不是 “把向右第一个 2 ...

  7. 插头DP讲解+[BZOJ1814]:Ural 1519 Formula 1(插头DP)

    1.什么是插头$DP$? 插头$DP$是$CDQ$大佬在$2008$年的论文中提出的,是基于状压$D$P的一种更高级的$DP$多用于处理联通问题(路径问题,简单回路问题,多回路问题,广义回路问题,生成 ...

  8. bzoj1814 Ural 1519 Formula 1(插头DP)

    对插头DP的理解还不是很透彻. 先说一下肤浅的理解吧. 插头DP使用范围:指数级复杂度,且适用于解决网格图连通性问题,如哈密顿回路等问题.插头一般指每相邻2个网格的接口. 题目难度:一般不可做. 使用 ...

  9. 【Ural】1519. Formula 1 插头DP

    [题目]1519. Formula 1 [题意]给定n*m个方格图,有一些障碍格,求非障碍格的哈密顿回路数量.n,m<=12. [算法]插头DP [题解]<基于连通性状态压缩的动态规划问题 ...

随机推荐

  1. 腾讯招聘网数据爬取存入mongodb

    #!/user/bin/env python3 # -*- coding: utf-8 -*- import requests from lxml import etree from math imp ...

  2. 017---Django的中间件解决跨域

    跨域 跨域是什么? 浏览器从一个域名的网页去请求另一个域名的资源的时候,如果不同源.请求的响应结果就会被浏览器的同源策略所拦截 同源策略是什么? 同源:协议 + 域名 + 端口 特点:阻止ajax请求 ...

  3. "Mon Dec 31 00:00:00 CST 2012" java日期装换 "yyyy-MM-dd"

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import ja ...

  4. Kubernetes-设计理念(三)

    Kubernetes设计理念与分布式系统 分析和理解Kubernetes的设计理念可以使我们更深入的了解Kubernetes系统,更好的利用它管理分布式部署的云原生应用,另一方面也可以让我们借鉴其在分 ...

  5. poj 2393 奶牛场生产成本问题 贪心算法

    题意:有一个奶牛场,第i周的生产成本为c,需要数量为 y,每周的存储成本为s.问怎么安排使得成本最低? 思路: 成本最低是吧?求出每周的最低成本*该周需要的数量就是成本最低 每周的成本有两个:自己本周 ...

  6. python爬取豌豆荚中的详细信息并存储到SQL Server中

    买了本书<精通Python网络爬虫>,看完了第6章,我感觉我好像可以干点什么:学的不多,其中的笔记我放到了GitHub上:https://github.com/NSGUF/PythonLe ...

  7. octave简易操作

    语言以分号;结尾if for while等语句后用,来承接关系if ,elseif ,else ,end;for i=1:10,end;while a>3 ,end;   while true, ...

  8. 查询如下课程平均成绩和及格率的百分数(用"1行"显示): 企业管理(001),马克思(002),OO&UML (003),数据库(004)

    SELECT SUM(CASE WHEN C# ='001' THEN score ELSE 0 END)/SUM(CASE C# WHEN '001' THEN 1 ELSE 0 END) AS 企 ...

  9. Code First Migrations更新数据库结构(数据迁移) 【转】

    注意:一旦正常后,每次数据库有变化,做如下两步: 1. Enable-Migrations 2.update-database 背景 code first起初当修改model后,要持久化至数据库中时, ...

  10. 初步学习pg_control文件之三

    接前文,初步学习pg_control文件之二 继续学习: 研究 DBState,先研究 DB_IN_PRODUCTION ,看它如何出现: 它出现在启动Postmaster时运行的函数处: /* * ...