今天早上学了插头DP的思想和最基础的应用,中午就开始敲了,岐哥说第一次写不要看别人代码,利用自己的理解一点点得写出来,这样才锻炼代码能力!于是下午慢慢地构思轮廓,一点点地敲出主体代码,其实是很磨蹭的,由于要考虑好多东西,而且昨晚2点睡的有点困,最后终于磨蹭出来了,第一次的代码搓没关系,自己写的才重要。然后果然不出我所料,调试到了晚上才A了(一个郁闷的错误)。。。A的感觉真的是爽呀,虽然搞了差不多一天。当然自己写了自己想的代码后也要把代码优化,不然队友看不懂自己代码就囧了。。。

插头DP,建议大家想学的好好看看陈丹琦的国家集训队论文,这是个优美的DP。

http://www.docin.com/p-46797997.html

#include <stdio.h>
#include <string.h> #define LL __int64 const int mod = 10007; // 哈希表
struct HASH{
int head[mod+10], E, next[80000];
LL val[80000], cnt[80000]; void init() {
memset(head, -1, sizeof(head));
E = 0;
} int findhash(LL x) {
return (x%mod + mod)%mod;
} void add(LL x, LL sum) {
int u = findhash(x);
for(int i = head[u];i != -1;i = next[i]) if(val[i] == x) {
cnt[i] += sum;
return ;
}
val[E] = x;
cnt[E] = sum;
next[E] = head[u];
head[u] = E++;
} }biao1, biao2; int c[22], n, m, d[22];
// 编码
void get(LL x) {
for(int i = m+1;i >= 1; i--) {
c[i] = x&7;
x /= 8;
}
}
// 解码
LL getval() {
LL ret = 0;
for(int i = 1;i <= m+1; i++) {
ret |= d[i];
ret *= 8;
}
ret /= 8;
return ret ;
}
// 转化成最小表示法
void change() {
int vis[22];
memset(vis, 0, sizeof(vis));
int num = 1;
for(int i = 1;i <= m+1;i ++) {
if(!d[i]) continue;
if(!vis[d[i]]) {
vis[d[i]] = num;
d[i] = num++;
}
else {
d[i] = vis[d[i]];
}
}
} void fuzhi() {
for(int i = 1;i <= m+1;i ++) d[i] = c[i];
} char s[22][22]; int main() {
int i, j, k, l;
while(scanf("%d%d", &n, &m) != -1) {
for(i = 1;i <= n; i++)
scanf("%s", s[i]+1);
int tot = 0;
for(i = 1;i <= n; i++)
for(j = 1;j <= m; j++)
if(s[i][j] == '.') tot++;
if(tot%2==1 || tot < 4) {
puts("0");
continue;
}
int tox = -1, toy = -1;
for(i = 1;i <= n; i++)
for(j = 1;j <= m; j++) if(s[i][j] == '.') {
tox = i;
toy = j;
}
biao1.init();
biao1.add(0, 1);
LL ans = 0;
for(i = 1;i <= n; i++){
for(j = 0;j <= m; j++){
biao2.init();
for(l = 0;l < biao1.E; l++) {
get(biao1.val[l]);
if(j == m) {
for(int ii = 2;ii <= m+1; ii++) d[ii] = c[ii-1];
d[1] = 0;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
continue;
}
if(c[j+1] && !c[j+2]) { // 有左插头无上插头
if(s[i][j+1] != '.') continue;
if(j+2 <= m) {
fuzhi();
d[j+1] = 0;d[j+2] = c[j+1];
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
if(i < n) {
fuzhi();
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
else if(!c[j+1] && c[j+2]) { // 有上插头无左插头
if(s[i][j+1] != '.') continue;
if(i < n) {
fuzhi();
d[j+1] = c[j+2]; d[j+2] = 0;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
if(j+2 <= m) {
fuzhi();
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
else if(!c[j+1] && !c[j+2]) { // 左和上都无插头
if(s[i][j+1] != '.') {
fuzhi();
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
continue;
}
if(j+2 <= m && i < n) {
fuzhi();
d[j+1] = d[j+2] = 13;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
else { //  左和上都有插头 ,  要判断左和上插头是否连通
if(c[j+2] == c[j+1]) {
int tot = 0;
for(int ii = 1;ii <= m+1; ii++) if(c[ii])
tot++;
if(tot == 2 && i == tox && j+1 == toy) ans += biao1.cnt[l];
}
else {
if(s[i][j+1] != '.') continue;
fuzhi();
for(int ii = 1;ii <= m+1; ii++) if(ii != j+1 && ii != j+2 && d[ii] == d[j+1]) {
d[ii] = d[j+2];
break;
}
d[j+1] = d[j+2] = 0;
change();
LL now = getval();
biao2.add(now, biao1.cnt[l]);
}
}
}
biao1 = biao2;
}
}
printf("%I64d\n", ans);
}
return 0;
}

Ural 1519. Formula 1 优美的插头DP的更多相关文章

  1. 【BZOJ1814】Ural 1519 Formula 1 (插头dp)

    [BZOJ1814]Ural 1519 Formula 1 (插头dp) 题面 BZOJ Vjudge 题解 戳这里 上面那个链接里面写的非常好啦. 然后说几个点吧. 首先是关于为什么只需要考虑三进制 ...

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

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

  3. bzoj1814 Ural 1519 Formula 1(插头dp模板题)

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

  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)

    1519. Formula 1 @ Timus Online Judge 干了一天啊!!!插头DP入门. 代码如下: #include <cstdio> #include <cstr ...

  6. URAL 1519 Formula 1(插头DP,入门题)

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

  7. HDU 1693 Eat the Trees(插头DP、棋盘哈密顿回路数)+ URAL 1519 Formula 1(插头DP、棋盘哈密顿单回路数)

    插头DP基础题的样子...输入N,M<=11,以及N*M的01矩阵,0(1)表示有(无)障碍物.输出哈密顿回路(可以多回路)方案数... 看了个ppt,画了下图...感觉还是挺有效的... 参考 ...

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

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

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

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

随机推荐

  1. 理解java Web项目中的路径问题

    本文以项目部署在tomcat服务器为例,其他相信也是一样的. 先说明请求页面的写法,在web中,页面路径主要写的有以下几种 1.请求重定向 2.浏览器的请求被服务器请求到新页面(我称为“转发”) 3. ...

  2. DFS的基础训练清单

    HDU 1010  (AC) HDU 1015    (AC) HDU 1016     (AC) HDU 1172   (AC) HDU 1312   (AC) POJ 2362  (AC,1011 ...

  3. C++常量的引用 const

    如果是对一个常量进行引用,则编译器首先建立一个临时变量,然后将该常量的值置入临时变量中,对该引用的操作就是对该临时变量的操作.对C++常量引用可以用其它任何引用来初始化:但不能改变. 关于引用的初始化 ...

  4. jQuery慢慢啃之回调(十三)

    1.callbacks.add(callbacks)//回调列表中添加一个回调或回调的集合 // a sample logging function to be added to a callback ...

  5. ueditor之ruby on rails 版

    最近公司的项目开始要使用ueditor了,但是ueditor却没有提供rails的版本,因此需要自己去定制化ueditor来满足项目的需求.不多说了,先简要说明下使用方法: ueditor目录下: 注 ...

  6. 控制反转(IoC)与依赖注入(DI)

    1.控制反转(Inversion of Control)与依赖注入(Dependency Injection) 控制反转即IoC (Inversion of Control),它把传统上由程序代码直接 ...

  7. jQuery中的data方法:

    向元素附加数据,然后取回该数据: $("#btn1").click(function(){ $("div").data("greeting" ...

  8. Java获取本机MAC地址

    为什么写这个呢?因为前几天看见网上有采用windows命令获取局域网和广域网MAC,查了查可以直接用JDK的方法. MAC可用于局域网验证,提高安全性. import java.net.InetAdd ...

  9. Warm up 2

    hdu4619:http://acm.hdu.edu.cn/showproblem.php?pid=4619 题意:题目大意:给你两种纸牌 ,一种水平放置共有n张 ,一种竖直放置共有m张.水平放置的纸 ...

  10. struts2不能通过ONGL方式取出request中的Atrribute

    请看下面一个很简单的Action package com.ahgw.main.action; import org.springframework.stereotype.Controller; /** ...