开学忙成狗,刷题慢如蜗牛……

【题目大意】

给出一个m*n的矩阵里面有一些格子为障碍物,一些格子只能上下通行,一些格子只能左右通行,一些格子上下左右都能通行。问经过所有非障碍格子的哈密顿回路个数。

【思路】

和BZOJ1814差不多,增加几个比较简单的判断即可。详见代码。

【错误点】

一开始我把三种可通行的情况写在一起,有点混乱了……拆开成3个函数就好啦!

下次注意程序的可读性。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN=;
const int HASH=;
int ex,ey;
int m,n;
int maze[MAXN][MAXN];
int code[MAXN],ch[MAXN];
struct HashMap
{
vector<int> hash[HASH];//存储f和state的下标
vector<ll> f,state;//存储对应的方案数和状态
void init()
{
for (int i=;i<HASH;i++) vector<int>().swap(hash[i]);
vector<ll>().swap(f);
vector<ll>().swap(state);
}
void push(ll st,ll ans)
{
int h=st%HASH;
for (int i=;i<hash[h].size();i++)
{
int now=hash[h][i];
if (state[now]==st)//如果已经存储了当前状态,直接累加
{
f[now]+=ans;
return;
}
}
//如果没有存储过当前状态,累加
state.push_back(st);
f.push_back(ans);
hash[h].push_back(state.size()-);
}
}dp[]; void decode(ll st)
{
memset(code,,sizeof(code));
for (int i=n;i>=;i--)
{
code[i]=st&;//每三位代表一个信息
st>>=;
}
} ll encode()
//用最小表示法重新编码
{
int cnt=;
memset(ch,-,sizeof(ch));
ch[]=;
long long st=;
for (int i=;i<=n;i++)
{
if (ch[code[i]]==-) ch[code[i]]=cnt++;
code[i]=ch[code[i]];
st<<=;
st|=code[i];
}
return st;
} void shift()
{
for (int i=n;i>;i--) code[i]=code[i-];
code[]=;
} void dpblank(int i,int j,int cur)
{
for (int k=;k<dp[-cur].state.size();k++)
{
decode(dp[-cur].state[k]);
int left=code[j-];//左插头
int up=code[j];//上插头 /*如果上下插头都没有*/
if (!left && !up)
{
if (maze[i][j+] && maze[i+][j])
{
code[j-]=code[j]=MAXN-;
//这里只要随便设置一个大数即可 //【attention】这里千万不可以设置成MAXN,否则ch数组会抱★★★★★★★★ //因为encode会重新用最小表示法编码
dp[cur].push(encode(),dp[-cur].f[k]);
}
} /*只有上插头或者只有左插头*/
if ((left&&(!up))||((!left)&&up))
{ int t=left|up;
if (maze[i][j+])//右边没有障碍
{
code[j-]=;
code[j]=t;
dp[cur].push(encode(),dp[-cur].f[k]);
}
if (maze[i+][j])//下面没有障碍
{
code[j-]=t;
code[j]=;
if (j==n) shift();
dp[cur].push(encode(),dp[-cur].f[k]);
}
} /*上插头和右插头都有*/
if (left && up)
{
if (left==up)
{
if (i==ex && j==ey)
{
code[j-]=code[j]=;
if (j==n) shift();
dp[cur].push(encode(),dp[-cur].f[k]);
}
}
else
{
code[j-]=code[j]=;
for (int t=;t<=n;t++)
if (code[t]==up) code[t]=left;
if (j==n) shift();
dp[cur].push(encode(),dp[-cur].f[k]);
}
}
}
} void DpHorizon(int cur,int i,int j)//只能水平走
{
for (int k=;k<dp[-cur].state.size();k++)
{
decode(dp[-cur].state[k]);
int left=code[j-],up=code[j]; if(!up && left&& maze[i][j+]!= && maze[i][j+]!=&& j!=n&&j!=) //右边不是障碍物,也能够水平走,并且不是最右边
{
code[j-]=;
code[j]=left;
dp[cur].push(encode(),dp[-cur].f[k]);
}
} } void DpVertical(int cur,int i,int j)//只能竖直走
{
for (int k=;k<dp[-cur].state.size();k++)
{
decode(dp[-cur].state[k]);
int left=code[j-],up=code[j]; if(up && !left && maze[i+][j]!= && maze[i+][j]!=&&i!=m&&i!=)//下边不是障碍物,也能够竖直走
{
code[j-]=up;
code[j]=;
if(j==n)shift();
dp[cur].push(encode(),dp[-cur].f[k]);
}
} } void dpblock(int i,int j,int cur)
{
int k=;
for (int k=;k<dp[-cur].state.size();k++)
{
decode(dp[-cur].state[k]);
code[j-]=code[j]=;
if (j==n) shift();
dp[cur].push(encode(),dp[-cur].f[k]);
}
} void solve()
{
int cur=;
ll ans=;
dp[cur].init();
dp[cur].push(,);//DP数组初始化
for (int i=;i<=m;i++)
for (int j=;j<=n;j++)
{
cur^=;
dp[cur].init();
if (maze[i][j]==) dpblank(i,j,cur);
else if (maze[i][j]==) dpblock(i,j,cur);
else if (maze[i][j]==)DpHorizon(cur,i,j);
else DpVertical(cur,i,j);
}
for (int i=;i<dp[cur].state.size();i++)
ans+=dp[cur].f[i];
printf("%lld",ans);
} void init()
{
scanf("%d%d",&m,&n);
for (int i=;i<=m;i++)
{
char str[MAXN];
scanf("%s",str);
for (int j=;j<=n;j++)
{
if (str[j-]=='#') maze[i][j]=;
if (str[j-]=='.') maze[i][j]=;
if (str[j-]=='-') maze[i][j]=;
if (str[j-]=='|') maze[i][j]=;
if (str[j-]!='#') ex=i,ey=j;
}
}
} int main()
{ init();
if (ex==) puts("");//如果没有一个是空格的话直接输出0
else solve(); }

【插头DP】BZOJ3125-city的更多相关文章

  1. 【bzoj3125】CITY 插头dp

    题目描述 给出一个n*m的矩阵,某些格子不能通过,某些格子只能上下通过或左右通过.求经过所有非不能通过格子的哈密顿回路条数. 输入 第一行有两个数N, M表示地图被分割成N*M个块,接下来有N行,每行 ...

  2. HDU 4064 Carcassonne(插头DP)(The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4064 Problem Description Carcassonne is a tile-based ...

  3. ural1519插头DP

    1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, that V ...

  4. 插头DP学习笔记——从入门到……????

    我们今天来学习插头DP??? BZOJ 2595:[Wc2008]游览计划 Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该 ...

  5. RUAL1519 Formula 1 【插头DP】

    RUAL1519 Formula 1 Background Regardless of the fact, that Vologda could not get rights to hold the ...

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

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

  7. URAL1519 Formula 1 —— 插头DP

    题目链接:https://vjudge.net/problem/URAL-1519 1519. Formula 1 Time limit: 1.0 secondMemory limit: 64 MB ...

  8. bzoj3125: CITY 题解

    3125: CITY Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 486  Solved: 213[Submit][Status][Discuss] ...

  9. [专题总结]初探插头dp

    彻彻底底写到自闭的一个专题. 就是大型分类讨论,压行+宏定义很有优势. 常用滚动数组+哈希表+位运算.当然还有轮廓线. Formula 1: 经过所有格子的哈密顿回路数. 每个非障碍点必须有且仅有2个 ...

  10. 「总结」插头$dp$

    集中做完了插头$dp$ 写一下题解. 一开始学的时候还是挺蒙的. 不过后来站在轮廓线$dp$的角度上来看就简单多了. 其实就是一种联通性$dp$,只不过情况比较多而已了. 本来转移方式有两种.逐行和逐 ...

随机推荐

  1. 微信小程序迁移到头条小程序工具

    最近公司需要将微信小程序迁移到头条小程序,比较得知微信和头条小程序的写法类似,只有文件名称不同,相关的指令不同,以及头条在ttml绑定的数据不可使用function,于是就写了node脚本来实现这些重 ...

  2. sicily 1240. Faulty Odometer

    Description You are given a car odometer which displays the miles traveled as an integer. The odomet ...

  3. openjudge-NOI 2.6-1996 登山

    题目链接:http://noi.openjudge.cn/ch0206/1996/ 题解: 正反求两次LIS即可 #include<cstdio> #include<cstring& ...

  4. TCP的状态兼谈Close_Wait和Time_Wait的状态

    原文链接: http://www.2cto.com/net/201208/147485.html TCP的状态兼谈Close_Wait和Time_Wait的状态   一 TCP的状态: 1).LIST ...

  5. Linux下如何创建新用户

    Linux下如何创建新用户 Linux系统中,只有root用户有创建其他用户的权限.创建过程如下:   useradd -d /home/newuser newuser(设定了该用户的主目录和用户名) ...

  6. Android学习笔记(三) UI布局

    每一个布局都有其适合的方式,另外,这几个布局元素可以相互嵌套应用,做出美观的界面. 一.线性布局(LinearLayout) 线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下 ...

  7. iOS客户端学习之AES加密

    数据加密在解密在软件开发过程中举足轻重的作用,可能有的公司在加密的时候有自己公司内部一套设计的算法,而在这方面不想浪费太大精力就可以去考虑使用第三方提供的加密算法,如AES加密算法,本篇内容介绍开源中 ...

  8. CircleIndicator

    dependencies { compile 'com.nineoldandroids:library:2.4.+' compile 'me.relex:circleindicator:1.0.0@a ...

  9. bzoj 1818 主席树

    思路:主席树搞一搞. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #de ...

  10. HTML5 Canvas 初探

    仅仅只是一个简单的hello world. js代码很简单: <!DOCTYPE HTML> <html lang="cn"> <head> & ...