题目1:BZOJ 1814 URAL 1519 Formula 1

题目大意:给定一个N*M的棋盘,上面有障碍格子。求一个经过所有非障碍格子形成的回路的数量。

插头DP入门题。记录连通分量。

 #include <bits/stdc++.h>

 using namespace std;

 const int maxd = ;
const int hash = ;
const int State = ;
typedef long long ll; ll ans = ;
int n, m;
int maze[maxd][maxd];
int code[maxd], ch[maxd];
int end_x, end_y;
char str[maxd]; struct HashMap {
int head[hash], next[State], size;
ll state[State], f[State]; void Init() {
size = ;
memset(head, -, sizeof head);
} void push(ll st, ll ans) {
int h = st % hash; for(int i = head[h]; i != -; i = next[i]) {
if(state[i] == st) {
f[i] += ans;
return;
}
}
state[size] = st;
f[size] = ans;
next[size] = head[h];
head[h] = size ++;
}
}dp[]; void decode(int *code, int s, ll st) {
for(int i = s; i >= ; -- i) {
code[i] = st & ;
st >>= ;
}
} ll encode(int *code, int s) {
int cnt = ;
ll st = ; memset(ch, -, sizeof ch);
ch[] = ;
for(int i = ; i <= s; ++ i) {
if(ch[code[i]] == -) ch[code[i]] = cnt ++;
code[i] = ch[code[i]];
st <<= ;
st |= code[i];
}
return st;
} void Shit(int *code, int s) {
for(int i = s; i >= ; -- i)
code[i] = code[i - ];
code[] = ;
} void dpblank(int x, int y, int cur) {
int left, up; for(int i = ; i < dp[cur].size; ++ i) {
decode(code, m, dp[cur].state[i]);
left = code[y - ];
up = code[y]; if(left && up) {
if(left == up) {
if(x == end_x && y == end_y) {
code[y - ] = code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(encode(code, m), dp[cur].f[i]);
}
}
else {
code[y - ] = code[y] = ;
for(int j = ; j <= m; ++ j)
if(code[j] == up)
code[j] = left;
if(y == m) Shit(code, m);
dp[cur ^ ].push(encode(code, m), dp[cur].f[i]);
}
}
else if((left && !up) || (!left && up)) {
int t; if(left) t = left;
else t = up;
if(maze[x][y + ]){
code[y - ] = ;
code[y] = t;
dp[cur ^ ].push(encode(code, m), dp[cur].f[i]);
}
if(maze[x + ][y]) {
code[y - ] = t;
code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(encode(code, m), dp[cur].f[i]);
}
}
else {
if(maze[x][y + ] && maze[x + ][y]) {
code[y - ] = code[y] = ;
dp[cur ^ ].push(encode(code, m), dp[cur].f[i]);
}
}
}
} void dpblock(int x, int y, int cur) {
for(int i = ; i < dp[cur].size; ++ i) {
decode(code, m, dp[cur].state[i]);
code[y - ] = code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(encode(code, m), dp[cur].f[i]);
}
} void Input() {
memset(maze, , sizeof maze); scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++ i) {
scanf("%s", str + );
for(int j = ; j <= m; ++ j) {
if(str[j] == '.') {
maze[i][j] = ;
end_x = i; end_y = j;
}
}
}
} void Solve() {
int cur = ;
ans = ; dp[cur].Init();
dp[cur].push(, );
for(int i = ; i <= n; ++ i) {
for(int j = ; j <= m; ++ j) {
dp[cur ^ ].Init();
if(maze[i][j]) dpblank(i, j, cur);
else dpblock(i, j, cur);
cur ^= ;
}
} for(int i = ; i < dp[cur].size; ++ i) {
ans += dp[cur].f[i];
} } void Output() {
printf("%lld\n", ans);
} int main(){
Input();
Solve();
Output(); return ;
}

BZOJ 1814

题目2:HDU 1693

求障碍棋盘上面多回路数。

因为求多回路,所以不一定在最后一个非障碍格子形成回路。只要当前状态相邻的两个格子有下插头和右插头,就是一个新的回路。所以对于此时的插头来说,我们可以不记插头所在的连通分量,只记录其是否存在即可。

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath> using namespace std; const int maxd = ;
const int Hash = ;
const int State = ;
typedef long long ll; ll ans = ;
int n, m;
int maze[maxd][maxd];
int code[maxd]; struct HashMap {
int head[Hash], next[State], size;
ll state[State], f[State]; void Init() {
size = ;
memset(head, -, sizeof head);
} void push(ll st, ll ans) {
int h = st % Hash; for(int i = head[h]; i != -; i = next[i]) {
if(state[i] == st) {
f[i] += ans;
return;
}
} f[size] = ans;
state[size] = st;
next[size] = head[h];
head[h] = size ++;
}
}dp[]; void opencode(int *code, int s, ll st) {
for(int i = s; i >= ; -- i) {
code[i] = st & ;
st >>= ;
}
} ll lockcode(int *code, int s) {
ll st = ; for(int i = ; i <= s; ++ i) {
st <<= ;
st |= code[i];
} return st;
} void Shit(int *code, int s) {
for(int i = s; i >= ; -- i) {
code[i] = code[i - ];
}
code[] = ;
} void dpblank(int x, int y, int cur) {
int left, up; for(int i = ; i < dp[cur].size; ++ i) {
opencode(code, m, dp[cur].state[i]);
left = code[y - ];
up = code[y];
if(left && up) {
code[y - ] = code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
else if(left || up) {
if(maze[x][y + ]) {
code[y - ] = ;
code[y] = ;
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
if(maze[x + ][y]) {
code[y - ] = ;
code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
}
else {
if(maze[x + ][y] && maze[x][y + ]) {
code[y - ] = code[y] = ;
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
}
}
} void dpblock(int x, int y, int cur) {
for(int i = ; i < dp[cur].size; ++ i) {
opencode(code, m, dp[cur].state[i]);
code[y - ] = code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
} void Input() {
scanf("%d%d", &n, &m);
memset(maze, , sizeof maze);
for(int i = ; i <= n; ++ i) {
for(int j = ; j <= m; ++ j) {
scanf("%d", &maze[i][j]);
}
}
} void Solve() {
int cur = ; dp[cur].Init();
dp[cur].push(, );
for(int i = ; i <= n; ++ i) {
for(int j = ; j <= m; ++ j) {
dp[cur ^ ].Init();
if(maze[i][j]) dpblank(i, j, cur);
else dpblock(i, j, cur);
cur ^= ;
}
} ans = ;
for(int i = ; i < dp[cur].size; ++ i) {
ans += dp[cur].f[i];
}
} void Output() {
printf("There are %lld ways to eat the trees.\n", ans);
} int main() {
int t, cnt = ; scanf("%d", &t); while(t --) {
++ cnt;
printf("Case %d: ", cnt);
Input();
Solve();
Output();
} return ;
}

HDU 1693

题目3: BZOJ 1210 HNOI 2004 邮递员

求一个棋盘上面从(1,1)到(N,N)有多少不同的路径。经过所有格子。

只要求一个回路。然后答案*2就可以了。要用高精度,不想打了,于是就Spj了一个极端数据。

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm> using namespace std; const int maxd = ;
const int State = ;
const int Hash = ;
typedef long long ll; int n, m;
ll Out_ans = ;
int code[maxd], ch[maxd]; struct HashMap {
int head[Hash], next[State], size;
ll f[State], state[State]; void Init() {
size = ;
memset(head, -, sizeof head);
} void push(ll st, ll ans) {
int h = st % Hash; for(int i = head[h]; i != -; i = next[i]) {
if(state[i] == st) {
f[i] += ans;
return;
}
} f[size] = ans;
state[size] = st;
next[size] = head[h];
head[h] = size ++;
}
}dp[]; void opencode(int *code, int s, ll st) {
for(int i = s; i >= ; -- i) {
code[i] = st & ;
st >>= ;
}
} ll lockcode(int *code, int s) {
int cnt = ;
ll st = ; memset(ch, -, sizeof ch);
ch[] = ;
for(int i = ; i <= s; ++ i) {
if(ch[code[i]] == -)
ch[code[i]] = cnt ++;
code[i] = ch[code[i]];
st <<= ;
st |= code[i];
} return st;
} void Shit(int *code, int s) {
for(int i = s; i >= ; -- i) {
code[i] = code[i - ];
}
code[] = ;
} void dpblank(int x, int y, int cur) {
int left, up; for(int i = ; i < dp[cur].size; ++ i) {
opencode(code, n, dp[cur].state[i]);
left = code[y - ];
up = code[y]; if(left && up) {
if(left == up) {
if(x == m && y == n) {
code[y - ] = ; code[y] = ;
if(y == n) Shit(code, n);
dp[cur ^ ].push(lockcode(code, n), dp[cur].f[i]);
}
}
else {
code[y - ] = code[y] = ;
for(int j = ; j <= n; ++ j)
if(code[j] == up)
code[j] = left;
if(y == n) Shit(code, n);
dp[cur ^ ].push(lockcode(code, n), dp[cur].f[i]);
}
}
else if(left || up) {
int t = ; if(left) t = left;
else t = up; if(x <= m && y + <= n) {
code[y - ] = ; code[y] = t;
dp[cur ^ ].push(lockcode(code, n), dp[cur].f[i]);
}
if(x + <= m && y <= n) {
code[y - ] = t; code[y] = ;
if(y == n) Shit(code, n);
dp[cur ^ ].push(lockcode(code, n), dp[cur].f[i]);
}
}
else {
if(x + <= m && y + <= n) {
code[y - ] = code[y] = ;
dp[cur ^ ].push(lockcode(code, n), dp[cur].f[i]);
}
}
}
} void Input() {
scanf("%d%d", &n, &m);
if(n == || m == ) {
puts("");
exit();
}
if(n == && m == ) {
puts(""); //不想写高精度
exit();
}
} void Solve() {
int cur = ; dp[cur].Init();
dp[cur].push(, );
for(int i = ; i <= m; ++ i) {
for(int j = ; j <= n; ++ j) {
dp[cur ^ ].Init();
dpblank(i, j, cur);
cur ^= ;
}
} for(int i = ; i < dp[cur].size; ++ i)
Out_ans += dp[cur].f[i];
} void Output() {
printf("%lld\n", Out_ans << );
} #define ONLINE_JUDGE
int main() {
#ifndef ONLINE_JUDGE
freopen("postman.in", "r", stdin);
freopen("postman.out", "w", stdout);
#endif Input();
Solve();
Output(); #ifndef ONLIEN_JUDGE
fclose(stdin); fclose(stdout);
#endif
return ;
}

BZOJ 1210

题目4: POJ 1739 Tony's Tour

在一个障碍棋盘上求从左下角到右下角的经过所有非障碍格子的数。

我们只要在最后面加上两行。

.******.

.............

这样就把左下角和右下角在这里边起来了。我们在这个新的棋盘中求回路方案数。那就是答案。

还是很好想的吧。

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <iostream> using namespace std; const int maxd = ;
const int State = ;
const int Hash = ;
typedef long long ll; int n, m;
int maze[maxd][maxd];
int code[maxd], ch[maxd];
ll Out_ans;
char str[]; struct HashMap {
int head[Hash], next[State], size;
ll f[State], state[State]; void Init() {
size = ;
memset(head, -, sizeof head);
} void push(ll st, ll ans) {
int h = st % Hash; for(int i = head[h]; i != -; i = next[i]) {
if(state[i] == st) {
f[i] += ans;
return;
}
} f[size] = ans;
state[size] = st;
next[size] = head[h];
head[h] = size ++;
}
}dp[]; void opencode(int *code, int s, ll st) {
for(int i = s; i >= ; -- i) {
code[i] = st & ;
st >>= ;
}
} ll lockcode(int *code, int s) {
int cnt = ;
ll st = ; memset(ch, -, sizeof ch);
ch[] = ;
for(int i = ; i <= s; ++ i) {
if(ch[code[i]] == -)
ch[code[i]] = cnt ++;
code[i] = ch[code[i]];
st <<= ;
st |= code[i];
}
return st;
} void Shit(int *code, int s) {
for(int i = s; i >= ; -- i) {
code[i] = code[i - ];
}
code[] = ;
} void dpblank(int x, int y, int cur) {
int left, up; for(int i = ; i < dp[cur].size; ++ i) {
opencode(code, m, dp[cur].state[i]);
left = code[y - ];
up = code[y]; if(left && up) {
if(left == up) {
if(x == n + && y == m) {
code[y - ] = code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
}
else {
code[y - ] = code[y] = ;
for(int j = ; j <= m; ++ j)
if(code[j] == up)
code[j] = left;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
}
else if(((!left) && up) || ((!up) && left)) {
int t = ; if(left) t = left;
else t = up; if(maze[x][y + ]) {
code[y - ] = ; code[y] = t;
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
if(maze[x + ][y]) {
code[y] = ; code[y - ] = t;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
}
else {
if(maze[x][y + ] && maze[x + ][y]) {
code[y - ] = code[y] = ;
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
}
}
} void dpblock(int x, int y, int cur) {
for(int i = ; i < dp[cur].size; ++ i) {
opencode(code, m, dp[cur].state[i]);
code[y - ] = code[y] = ;
if(y == m) Shit(code, m);
dp[cur ^ ].push(lockcode(code, m), dp[cur].f[i]);
}
} int main() {
while(scanf("%d%d", &n, &m) && n && m) {
memset(maze, , sizeof maze); for(int i = ; i <= n; ++ i) {
scanf("%s", str + );
for(int j = ; j <= m; ++ j) {
if(str[j] == '.')
maze[i][j] = ;
}
}
for(int i = ; i <= m; ++ i) {
maze[n + ][i] = ;
}
maze[n + ][] = ; maze[n + ][m] = ; int cur = ; dp[cur].Init();
dp[cur].push(, );
for(int i = ; i <= n + ; ++ i) {
for(int j = ; j <= m; ++ j) {
dp[cur ^ ].Init();
if(maze[i][j])
dpblank(i, j, cur);
else
dpblock(i, j, cur);
cur ^= ;
}
} Out_ans = ;
for(int i = ; i < dp[cur].size; ++ i) {
Out_ans += dp[cur].f[i];
} printf("%lld\n", Out_ans);
} return ;
}

POJ 1739

插头DP题目泛做(为了对应WYD的课件)的更多相关文章

  1. 数学期望和概率DP题目泛做(为了对应AD的课件)

    题1: Uva 1636 Headshot 题目大意: 给出一个000111序列,注意实际上是环状的.问是0出现的概率大,还是当前是0,下一个还是0的概率大. 问题比较简单,注意比较大小: A/C & ...

  2. 后缀自动机/回文自动机/AC自动机/序列自动机----各种自动机(自冻鸡) 题目泛做

    题目1 BZOJ 3676 APIO2014 回文串 算法讨论: cnt表示回文自动机上每个结点回文串出现的次数.这是回文自动机的定义考查题. #include <cstdlib> #in ...

  3. 基尔霍夫矩阵题目泛做(AD第二轮)

    题目1: SPOJ 2832 题目大意: 求一个矩阵行列式模一个数P后的值.p不一定是质数. 算法讨论: 因为有除法而且p不一定是质数,不一定有逆元,所以我们用辗转相除法. #include < ...

  4. FFT与多项式、生成函数题目泛做

    题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 #include <cstdlib> #include <iostream> #include <algorit ...

  5. 二维计算几何基础题目泛做(SYX第一轮)

    题目1: POJ 2318 TOYS 题目大意: 给一个有n个挡板的盒子,从左到右空格编号为0...n.有好多玩具,问每个玩具在哪个空格里面. 算法讨论: 直接叉积判断就可以.注意在盒子的边界上面也算 ...

  6. 生成树题目泛做(AD第二轮)

    题目1: NOI2014 魔法森林 LCT维护MST.解题报告见LOFTER #include <cstdio> #include <iostream> #include &l ...

  7. noi往届题目泛做

    noi2015 Day1 t1 程序自动分析  离散化+并查集 t2 软件包管理器  裸树链剖分 t3 寿司晚宴  状压dp Day2 t1 荷马史诗 哈夫曼多叉树 t2 品酒大会 后缀数组按照hei ...

  8. K-D Tree题目泛做(CXJ第二轮)

    题目1: BZOJ 2716 题目大意:给出N个二维平面上的点,M个操作,分为插入一个新点和询问到一个点最近点的Manhatan距离是多少. 算法讨论: K-D Tree 裸题,有插入操作. #inc ...

  9. Link-Cut-Tree题目泛做(为了对应自己的课件)

    题目1:BZOJ 2049 洞穴勘测 #include <bits/stdc++.h> #define L(x) c[x][0] #define R(x) c[x][1] using na ...

随机推荐

  1. JSP 核心 (等待更新)

    开篇:JSP的等同于servlet 编译器将其转化为.class,后执行.一旦配置在Tomcat webapps,运行访问后,在Tomcat--->work文件内出现java文件,其内容即为转化 ...

  2. poj2709 贪心基础

    D - 贪心 基础 Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bi ...

  3. JDBC中PreparedStatement和Statement的区别

    共同点: PreparedStatement和Statement都是用来执行SQL查询语句的API之一. 不同点: 在PreparedStatement中,当我们经常需要反复执行一条结构相似的sql语 ...

  4. 安装完Apache和PHP之后访问PHP文件页面提示下载而没有解析 解决办法

    装好LAMP环境后,还要做下整合Apache与PHP相关配置,在apache配置文件里找到:AddType application/x-gzip .gz .tgz在该行下面添加AddType appl ...

  5. C 中va_list,va_arg,va_start,va_end usage

    1.在学习c语言,难免会遇到多参函数,刚好c中也提供了一些机制:宏函数 #ifdef _M_ALPHA typedef struct { char *a0; /* pointer to first h ...

  6. CC2530定时器1的模模式中断

    CC2530定时器1的模模式中断void timer1SInit(void){ T1CCTL0 = 0; T1CTL &= ~0x0F; //clear register T1CTL |= 0 ...

  7. HTML中select标签单选多选详解

    select 元素可创建单选或多选菜单.当提交表单时,浏览器会提交选定的项目,或者收集用逗号分隔的多个选项,将其合成一个单独的参数列表,并且在将 <select> 表单数据提交给服务器时包 ...

  8. 163k地方门户网站系统js小Bug

    163k地方门户网站系统后台在Firefox下无法通过选择区域来获取相对应的地段,IE浏览器下无些问题. Firebug提示错误为: ReferenceError: requestdataquyu i ...

  9. CNN(卷积神经网络)、RNN(循环神经网络)、DNN(深度神经网络)的内部网络结构有什么区别?

    https://www.zhihu.com/question/34681168 CNN(卷积神经网络).RNN(循环神经网络).DNN(深度神经网络)的内部网络结构有什么区别?修改 CNN(卷积神经网 ...

  10. SHELL种类,版本及选择

    SHELL种类,版本及选择 凡是使用 *INX 的人,不论是作为 login shell 还是编程,多少都要接触到 Shell.经过多年的发展, Shell 的种类繁多.除了我们熟悉的 sh.ksh. ...