【BZOJ 3049】【USACO2013 Jan】Island Travels BFS+状压DP
这是今天下午的互测题,只得了60多分
分析一下错因:
$dis[i][j]$只记录了相邻的两个岛屿之间的距离,我一开始以为可以,后来$charge$提醒我有可能会出现来回走的情况,而状压转移就一次,无法实现来回走的情况,所以加了一个类似$floyed算法$的三重循环来更新每个点的距离,然后状态转移就可以了,枚举起点和终点,最后统计答案
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char c[53][53];
int n, m, dis[18][18], belong[53][53], f[40000][18], cnt = 0, qx[2500000], qy[2500000];
int far[2500000], head, tail;
bool vis[53][53];
inline void _(int x, int y) {
belong[x][y] = cnt;
vis[x][y] = 1;
if (x > 1 && c[x - 1][y] == 'X' && !vis[x - 1][y])
_(x - 1, y);
if (y > 1 && c[x][y - 1] == 'X' && !vis[x][y - 1])
_(x, y - 1);
if (x < n && c[x + 1][y] == 'X' && !vis[x + 1][y])
_(x + 1, y);
if (y < m && c[x][y + 1] == 'X' && !vis[x][y + 1])
_(x, y + 1);
}
inline void __(int x) {
int nowx, nowy;
while (head != tail) {
++head; if ( head >= 2500000) head %= 2500000;
nowx = qx[head];
nowy = qy[head];
if (nowx > 1 && !vis[nowx - 1][nowy] && c[nowx - 1][nowy] != '.') {
if (c[nowx - 1][nowy] == 'S') {
++tail; if (tail >= 2500000) tail %= 2500000;
qx[tail] = nowx - 1;
qy[tail] = nowy;
far[tail] = far[head] + 1;
vis[nowx - 1][nowy] = 1;
} else {
dis[x][belong[nowx - 1][nowy]] = min( dis[x][belong[nowx - 1][nowy]], far[head]);
}
}
if (nowy > 1 && !vis[nowx][nowy - 1] && c[nowx][nowy - 1] != '.') {
if (c[nowx][nowy - 1] == 'S') {
++tail; if (tail >= 2500000) tail %= 2500000;
qx[tail] = nowx;
qy[tail] = nowy - 1;
far[tail] = far[head] + 1;
vis[nowx][nowy - 1] = 1;
} else {
dis[x][belong[nowx][nowy - 1]] = min( dis[x][belong[nowx][nowy - 1]], far[head]);
}
}
if (nowx < n && !vis[nowx + 1][nowy] && c[nowx + 1][nowy] != '.') {
if (c[nowx + 1][nowy] == 'S') {
++tail; if (tail >= 2500000) tail %= 2500000;
qx[tail] = nowx + 1;
qy[tail] = nowy;
far[tail] = far[head] + 1;
vis[nowx + 1][nowy] = 1;
} else {
dis[x][belong[nowx + 1][nowy]] = min( dis[x][belong[nowx + 1][nowy]], far[head]);
}
}
if (nowy < m && !vis[nowx][nowy + 1] && c[nowx][nowy + 1] != '.') {
if (c[nowx][nowy + 1] == 'S') {
++tail; if (tail >= 2500000) tail %= 2500000;
qx[tail] = nowx;
qy[tail] = nowy + 1;
far[tail] = far[head] + 1;
vis[nowx][nowy + 1] = 1;
} else {
dis[x][belong[nowx][nowy + 1]] = min( dis[x][belong[nowx][nowy + 1]], far[head]);
}
}
}
}
int main() {
scanf("%d%d\n", &n, &m);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) {
c[i][j] = getchar();
while (c[i][j] != 'X' && c[i][j] != '.' && c[i][j] != 'S')
c[i][j] = getchar();
}
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if (!vis[i][j] && c[i][j] == 'X') {
++cnt;
_(i, j);
}
memset(dis, 1, sizeof(dis));
for(int i = 1; i <= cnt; ++i) {
head = 0;
tail = 0;
memset(vis, 0, sizeof(vis));
for(int k = 1; k <= n; ++k)
for(int l = 1; l <= m; ++l)
if (belong[k][l] == i) {
vis[k][l] = 1;
++tail; if ( tail >= 2500000) tail %= 2500000;
qx[tail] = k;
qy[tail] = l;
far[tail] = 0;
}
__(i);
}
for(int k = 1; k <= cnt; ++k)
for(int i = 1; i <= cnt; ++i)
for(int j = 1; j <= cnt; ++j)
if (dis[i][k] + dis[k][j] < dis[i][j])
dis[i][j] = dis[i][k] + dis[k][j];
memset(f, 1, sizeof(f));
int ans = 500000, tot = (1 << cnt) - 1;
for(int i = 1; i <= cnt; ++i)
f[1 << ( i - 1)][i] = 0;
for(int i = 1; i <= tot; ++i) {
for(int j = 1; 1 << (j - 1) <= i; ++j) {
if (1 << (j - 1) & i) {
for(int k = 1; k <= cnt; ++k)
if (k != j && (1 << (k - 1) & i))
f[i][j] = min(f[i][j], f[i ^ (1 << (j - 1))][k] + dis[k][j]);
}
}
}
for(int i = 1; i <= cnt; ++i)
ans = min(ans, f[tot][i]);
printf("%d\n",ans);
return 0;
}
以后思维得更严谨才行
我的BFS写的就是这么丑,这又怎样?
【BZOJ 3049】【USACO2013 Jan】Island Travels BFS+状压DP的更多相关文章
- BZOJ_3049_[Usaco2013 Jan]Island Travels _状压DP+BFS
BZOJ_3049_[Usaco2013 Jan]Island Travels _状压DP+BFS Description Farmer John has taken the cows to a va ...
- hdu 4856 Tunnels (bfs + 状压dp)
题目链接 The input contains mutiple testcases. Please process till EOF.For each testcase, the first line ...
- HDU-4856 Tunnels (BFS+状压DP)
Problem Description Bob is travelling in Xi’an. He finds many secret tunnels beneath the city. In hi ...
- 孤岛营救问题(BFS+状压DP)
孤岛营救问题 https://www.luogu.org/problemnew/show/P4011 用状压DP标记拿到钥匙的数量 #include<iostream> #include& ...
- QDUOJ 来自xjy的签到题(bfs+状压dp)
来自xjy的签到题 Description 爱丽丝冒险来到了红皇后一个n*n大小的花园,每个格子由'.'或'#'表示,'.'表示爱丽丝可以到达这个格子,‘#’表示爱丽丝不能到达这个格子,爱丽丝每1 ...
- HDU-3681-Prison Break(BFS+状压DP+二分)
Problem Description Rompire is a robot kingdom and a lot of robots live there peacefully. But one da ...
- bzoj 1879 [Sdoi2009]Bill的挑战(状压DP)
Description Input 本题包含多组数据. 第一行:一个整数T,表示数据的个数. 对于每组数据: 第一行:两个整数,N和K(含义如题目表述). 接下来N行:每行一个字符串. Output ...
- bzoj 1226 [SDOI2009]学校食堂Dining(状压DP)
Description 小F 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜肴.当然,不同的人口味也不一定相同,但每个人的口味都可以 ...
- #12【BZOJ3003】LED BFS+状压DP
题解: 看到区间修改先想一下差分 这题用差分是为了分析问题 现在的问题就变成了 原序列全为0,要使得特定的k个点变为1,每个操作改变x,y+1 然后我们会发现 对于二元组a,b我们要修改它,实际上是在 ...
随机推荐
- CSS样式----图文详解(二):css属性
主要内容 CSS的单位 字体属性 文本属性 背景属性 列表属性 盒子模型 定位属性:position.float.overflow.z-index等 导航栏的制作 鼠标的属性cursor 滤镜的介绍 ...
- luogu10125回文数[noip1999 Day1 T1]
题目描述 若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数. 例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数. 又如:对于10进制数 ...
- HTML 学习笔记 CSS(选择器3)
CSS 属性选择器 属性选择器可以根据元素的额属性以及属性值来选择元素 例子1 如果 你希望把包含title的所有元素变成红色 *[title] {color:red} 例子2 与上面类似 可以只对有 ...
- HTML 学习笔记(块 和 类)
HTML <div> 和 <span> 可以通过<div>和<span>将HTML元素组合起来. HTML块元素 大多数HTML元素被定义为块级元素或者 ...
- PAT 1011. A+B和C (15)
给定区间[-231, 231]内的3个整数A.B和C,请判断A+B是否大于C. 输入格式: 输入第1行给出正整数T(<=10),是测试用例的个数.随后给出T组测试用例,每组占一行,顺序给出A.B ...
- 产品经理技能之MRD的笔记之一
原文:http://www.woshipm.com/pmd/131946.html/comment-page-1 产品经理技能之MRD 一.MRD与BRD的不同之处 BRD:这么做有什么好处,并说明好 ...
- android 打Patch的方法 .
http://blog.csdn.net/sunyubo458/article/details/6680840 作为程序员,了解diff&patch命 令是非常必要的.比如说我们发现某个项目有 ...
- typedef 和define的区别
总结一下typedef和#define的区别 1.概念 #define 它在编译预处理时进行简单的替换,不作正确性检查.它是预处理指令. typedef 它在自己的作用域内给一个已经存在的类型一个别名 ...
- 深入理解Message, MessageQueue, Handler和Looper
做过Android的都知道Message, MessageQueue, Handler和Looper,但知道不代表你理解它们.有时觉得用得很顺手,但Android怎么实现又说不上来,总觉得似懂非懂.不 ...
- C#迭代器
迭代器概述 迭代器是可以返回相同类型的值的有序序列的一段代码. 迭代器可用作方法.运算符或 get 访问器的代码体. 迭代器代码使用 yield return 语句依次返回每个元素.yield bre ...