题目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. C#串口扫描

    1.传入serialport 和待显示串口的Commbox private void Search_AddSerialToComboBox(SerialPort MyPort, ComboBox My ...

  2. django web 中添加超链接

    django web 中添加不传参的超链接的方法如下: html: 在web中的超链接中加入一下url <a href="{% url 'app_name.views.url_func ...

  3. 关于Windows8.1更新后Sql Server服务消失的处理办法

    前言 微软在17日发布了windows8.1,兴致勃勃地花了半天的时间更新了,不过不知所云的是,在20日又被卸下Windows Store.此为背景. 影响 更新完毕做开发的时候,发现SqlServe ...

  4. wordpress显示多个分类的文章

    显示多个分类下的文章可以这样提取: <?php query_posts(array('posts_per_page'=>10,'orderby'=>'rand','category_ ...

  5. HornetQ

    https://github.com/flsusp/http-queue https://github.com/sfr-network-service-platforms/hq-console htt ...

  6. HDU4532(组合DP)

    题目:安排座位 解析:http://www.douban.com/note/269136472/ #include <iostream> #include <string.h> ...

  7. 商派shopex

    http://www.shopex.cn/48release/shopexsingle_exper.php 在线体验 前台体验:http://demo.shopex.com.cn/485 后台体验:h ...

  8. mysql5.5 无法创建实例,error 16001

    今天想用jdbc做个小程序,结果发现好久不用的mysql不好用了,我装的是社区版(win7)环境下,按理说不可能出问题,找了一堆解决方案都没解决,准备重装的时候想把mysql服务停了,直接在dos输入 ...

  9. IOS开发错误提示原因集合-----长期更新

    "[__NSCFConstantString size]: unrecognized selector sent to instance." =>将NSString类型的参数 ...

  10. 异步化DAO的设计和实践

    目前,公司技术规划要求未来所有的服务要全面实现异步化接口,使得每个服务能达到1万/秒的单机性能.我们知道,在一个服务请求中,可能会调用其他服务,还会使用memcache.kv以及mysql等.目前,大 ...