题目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. ASP.NET MVC4 + Highcharts生成报表

    //后端 public ActionResult TighteningReport(BReportTighteningReportModel model, string rate, string we ...

  2. Java 中字符串的子串搜索

    基友前两天参加了阿里的实习生面试,问了个问题,就是关于字符串的子串搜索的问题.想想实现方式无非就是两层循环,但是 java 中是有现成实现的,于是我就去查查源码,看看 java 语言怎么实现这个的,发 ...

  3. destoon控制标题长度,title中显示全标题 标题字符长度怎么控制?

    如题商品调用出来后,标题的字符长度怎么控制?有哪位高手能帮我解决吗? 小弟在此感谢了. &length=30 //30表示30个字节 <!--{tag("moduleid=5& ...

  4. Python Set集合,函数,深入拷贝,浅入拷贝,文件处理

    1.Set基本数据类型 a.set集合,是一个无序且不重复的元素集合 class set(object): """ set() -> new empty set o ...

  5. R语言画正弦曲线

    正弦曲线一个周期是2π,我们要先生成x的取值范围. 可以用seq函数生成一个等差序列,步进为0.01 x=seq( 0,  2*pi,  0.01 )   pi表示π y=sin(x) plot(x, ...

  6. 深入理解 静态类和静态字段(C# 基础)

    序言 以前,总是被提醒,在编程过程中尽量少用静态变量,数据丢失什么的,今天有空,禁不住对静态变量的强烈好奇,跟我一起了解下静态家族的内幕吧. 静态类 定义 静态类与非静态类的重要区别在于静态类不能实例 ...

  7. 读mongoose api 记录

    mongoose 需要在Schemas基础上进行使用 var mongoose = require('mongoose'); var Schema = mongoose.Schema; var blo ...

  8. Linux配置完iptables后,重启失效的解决方案

    Linux配置完iptables后,重启失效的解决方案 因为只有root用户才可访问1024以下的端口,非root用户登陆是不能启用80端口的.web service 往往启动1024以上的端口,并通 ...

  9. 理解 Linux 配置文件分类和使用

    理解 Linux 配置文件分类和使用 本文说明了 Linux 系统的配置文件,在多用户.多任务环境中,配置文件控制用户权限.系统应用程序.守护进程.服务和其它管理任务.这些任务包括管理用户帐号.分配磁 ...

  10. Spiral Matrix II 解答

    Question Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral or ...