poj 1729 Jack and Jill 1376 Robot 1324 Holedox Moving 1475 Pushing Boxes bfs + a*
2015-08-29 20:53
721 查看
poj 1729 Jack and Jill
Jack和Jill要从各自的家走到各自的学校,但是他们俩各自不喜欢对方,因此,需要你找到两个人行走的路线,使得他们路线中两个人最近的直线距离最长。单位时间内,每个人都可以走到相邻的四个格子中。只考虑移动过后两个人所在位置的直线距离。走过的路可以来回走,到达学校之后就不能离开学校了。其中H,S分别表示Jack的家和学校;h,s分别表示jill的家和学校;*表示两人都不可以走的区域;Jack的家和学校Jill使不能走的,Jill的家和学校Jill也是不能走的。
每个单位时间,Jack和Jill可以从当前位置向相邻的区域走,因为要求走的过程中,两人走的路线距离最近的地方尽可能大,所以每次应该找到队列中点对距离最大的点扩展,所以应该使用优先队列,因为走过的点还可以再走,所以用一个vis[x1][y1][x2][y2]数组来标记当前状态的最优解,也就是说从起点走到这个位置距离最近的时候的最大值。因为还要记录路径,所以把队列中经过的点都存起来,记录上一个点,然后到达结束状态的时候,反着求出来路径。
/************************************************************************* > File Name: 1729.cpp > Author: gwq > Mail: gwq5210@qq.com > Created Time: 2015年08月11日 星期二 15时42分37秒 ************************************************************************/ #include <cmath> #include <ctime> #include <cctype> #include <climits> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> #include <set> #include <queue> #include <stack> #include <string> #include <vector> #include <sstream> #include <iostream> #include <algorithm> #define INF (INT_MAX / 10) #define clr(arr, val) memset(arr, val, sizeof(arr)) #define pb push_back #define sz(a) ((int)(a).size()) using namespace std; typedef set<int> si; typedef vector<int> vi; typedef map<int, int> mii; typedef pair<int, int> pii; typedef long long ll; const double esp = 1e-5; #define N 35 struct Node; int n, vis ; int sx1, sy1, sx2, sy2, ex1, ey1, ex2, ey2, cnt; int dx[] = {0, -1, 0, 1}; int dy[] = {1, 0, -1, 0}; char direct[] = "ENWS"; char mp ; int dist(int x1, int y1, int x2, int y2) { return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); } struct Node { int x1, y1, x2, y2, dis, d1, d2, id, pre; Node() {} Node(int a, int b, int c, int d, int dd) :x1(a), y1(b), x2(c), y2(d), dis(dd) {} void output(void) { printf("dis = %d\n", dis); printf("x1 = %d, y1 = %d.\n", x1, y1); printf("x2 = %d, y2 = %d.\n", x2, y2); printf("-----------------\n"); } bool check(void) { if (check1() && check2()) { return true; } else { return false; } } bool check1(void) { if (x1 == ex1 && y1 == ey1) { return true; } else { return false; } } bool check2(void) { if (x2 == ex2 && y2 == ey2) { return true; } else { return false; } } bool operator <(const Node v) const { return this->dis < v.dis; } }way[1000010]; void bfs(void) { priority_queue<Node> q; clr(vis, -1); Node v = Node(sx1, sy1, sx2, sy2, dist(sx1, sy1, sx2, sy2)); cnt = 1; v.d1 = -1; v.d2 = -1; v.id = 0; v.pre = -1; q.push(v); way[0] = v; vis[sx1][sy1][sx2][sy2] = v.dis; while (!q.empty()) { Node u = q.top(); q.pop(); //u.output(); if (u.check()) { printf("%.2f\n", sqrt(1.0 * u.dis)); Node p = u; string s1, s2; while (p.pre != -1) { if (p.d1 != '*') { s1.pb(p.d1); } if (p.d2 != '*') { s2.pb(p.d2); } p = way[p.pre]; } reverse(s1.begin(), s1.end()); reverse(s2.begin(), s2.end()); cout << s1 << endl; cout << s2 << endl; return; } for (int i = 0; i < 4; ++i) { int nx1 = u.x1 + dx[i]; int ny1 = u.y1 + dy[i]; int d1 = direct[i]; if (u.check1()) { nx1 = u.x1; ny1 = u.y1; d1 = '*'; } if (!mp[nx1][ny1] || mp[nx1][ny1] == '#' || mp[nx1][ny1] == '*') { ; } else { for (int j = 0; j < 4; ++j) { int nx2 = u.x2 + dx[j]; int ny2 = u.y2 + dy[j]; int d2 = direct[j]; if (u.check2()) { nx2 = u.x2; ny2 = u.y2; d2 = '*'; } if (!mp[nx2][ny2] || mp[nx2][ny2] == '$' || mp[nx2][ny2] == '*') { ; } else { int ndis = dist(nx1, ny1, nx2, ny2); ndis = min(ndis, u.dis); int vv = vis[nx1][ny1][nx2][ny2]; if (vv == -1 || ndis > vis[nx1][ny1][nx2][ny2]) { vis[nx1][ny1][nx2][ny2] = ndis; v = Node(nx1, ny1, nx2, ny2, ndis); v.d1 = d1; v.d2 = d2; v.pre = u.id; v.id = cnt; q.push(v); way[cnt++] = v; } } } } } } return; } int main(int argc, char *argv[]) { while (scanf("%d", &n) != EOF) { if (!n) { break; } clr(mp, 0); for (int i = 1; i <= n; ++i) { scanf("%s", mp[i] + 1); for (int j = 1; j <= n; ++j) { if (mp[i][j] == 'H') { sx1 = i; sy1 = j; mp[i][j] = '$'; } else if (mp[i][j] == 'S') { ex1 = i; ey1 = j; mp[i][j] = '$'; } else if (mp[i][j] == 'h') { sx2 = i; sy2 = j; mp[i][j] = '#'; } else if (mp[i][j] == 's') { ex2 = i; ey2 = j; mp[i][j] = '#'; } } } bfs(); } return 0; }
poj 1376 Robot
机器人想要从一个地点到另一个地点,机器人是有直径的,而且机器人只能在格子的交点上移动,但是格子里可能是一些障碍物,因为机器人有直径,所以,在障碍物的周围,机器人是走不到的,也就是说,障碍物阻碍的范围变大了,可以读入障碍物位置的时候将其障碍住的交点弄上标记,但是不要读完之后再去标记,因为这不能确定这里本身是一个障碍物还是障碍物扩展来的。也可以读入的时候不判断,而在扩展的时候动态的判断。因为数据比较小,没有用A*也可以过。/************************************************************************* > File Name: 1376.cpp > Author: gwq > Mail: gwq5210@qq.com > Created Time: 2015年08月14日 星期五 20时01分24秒 ************************************************************************/ #include <cmath> #include <ctime> #include <cctype> #include <climits> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> #include <set> #include <queue> #include <stack> #include <string> #include <vector> #include <sstream> #include <iostream> #include <algorithm> #define INF (INT_MAX / 10) #define clr(arr, val) memset(arr, val, sizeof(arr)) #define pb push_back #define sz(a) ((int)(a).size()) using namespace std; typedef set<int> si; typedef vector<int> vi; typedef map<int, int> mii; typedef pair<int, int> pii; typedef long long ll; const double esp = 1e-5; #define N 55 int mp , n, m, sx, sy, ex, ey, vis [4], sd; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; char type[100]; struct Node { int x, y, s, d, pre, id; Node() {} Node(int xx, int yy, int ss, int dd): x(xx), y(yy), s(ss), d(dd) {} bool check(void) { if (x == ex && y == ey) { return true; } else { return false; } } void output(void) { printf("x = %d, y = %d, s = %d, d = %d, id = %d, pre = %d\n", x, y, s, d, id, pre); } }; bool check(int x, int y) { if (x <= 0 || y <= 0 || x >= n || y >= m) { return false; } if (mp[x][y] || mp[x - 1][y - 1] || mp[x - 1][y] || mp[x][y - 1]) { return false; } return true; } int bfs(void) { queue<Node> q; clr(vis, 0); Node u = Node(sx, sy, 0, sd); u.pre = -1; u.id = 0; q.push(u); vis[sx][sy][sd] = 1; int cnt = 0; while (!q.empty()) { u = q.front(); q.pop(); //u.output(); //getchar(); if (u.check()) { return u.s; } Node v; int nd = (u.d + 1) % 4; if (!vis[u.x][u.y][nd]) { v = Node(u.x, u.y, u.s + 1, nd); v.pre = u.id; v.id = cnt++; q.push(v); vis[u.x][u.y][nd] = 1; } nd = (u.d + 3) % 4; if (!vis[u.x][u.y][nd]) { v = Node(u.x, u.y, u.s + 1, nd); v.pre = u.id; v.id = cnt++; q.push(v); vis[u.x][u.y][nd] = 1; } for (int i = 1; i <= 3; ++i) { int ns = u.s + 1; int nx = u.x + i * dx[u.d]; int ny = u.y + i * dy[u.d]; bool flag = check(nx, ny); if (!flag) { break; } //printf("%d %d %d %d...\n", nx, ny, mp[nx][ny], check(nx, ny)); if (!vis[nx][ny][u.d]) { v = Node(nx, ny, ns, u.d); v.pre = u.id; v.id = cnt++; q.push(v); vis[nx][ny][u.d] = 1; } } } return -1; } int main(int argc, char *argv[]) { while (scanf("%d%d", &n, &m) != EOF) { if (n == 0 && m == 0) { break; } clr(mp, 0); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &mp[i][j]); } } scanf("%d%d%d%d%s", &sx, &sy, &ex, &ey, type); switch (type[0]) { case 'n': sd = 0; break; case 'e': sd = 1; break; case 's': sd = 2; break; case 'w': sd = 3; break; } printf("%d\n", bfs()); } return 0; }
poj 1324 Holedox Moving
一个蛇需要从当前位置移动到指定的位置,因为蛇身体不好保存,所以,用一个整数压缩一下,具体做法是记录蛇头的位置,身体的其他部分记录前一个到当前的方向,因为只有4个方向,所以就可以用2位表示,因为蛇身体最长为8,那么用蛇头在位置x,y就最多有2<<14个状态,因为蛇头的位置不需要再记录了。每次扩展的时候判断是不是蛇身体或者障碍物就行了。
可以使用曼哈顿距离作为启发函数。
/************************************************************************* > File Name: 1324.cpp > Author: gwq > Mail: gwq5210@qq.com > Created Time: 2015年08月15日 星期六 21时45分46秒 ************************************************************************/ #include <cmath> #include <ctime> #include <cctype> #include <climits> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> #include <set> #include <queue> #include <stack> #include <string> #include <vector> #include <sstream> #include <iostream> #include <algorithm> #define INF (INT_MAX / 10) #define clr(arr, val) memset(arr, val, sizeof(arr)) #define pb push_back #define sz(a) ((int)(a).size()) using namespace std; typedef set<int> si; typedef vector<int> vi; typedef map<int, int> mii; typedef pair<int, int> pii; typedef long long ll; const double esp = 1e-5; #define N 25 int mp , n, m, l, vis [1 << 14]; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; int bx[10]; int by[10]; int getdir(int x, int y, int a, int b) { for (int i = 0; i < 4; ++i) { if (x + dx[i] == a && y + dy[i] == b) { return i; } } return -1; } struct Node { int x, y, d, st, h; Node () {} Node(int xx, int yy, int dd, int sst): x(xx), y(yy), d(dd), st(sst) {} void output(void) { printf("x = %d, y = %d, d = %d, st = %d, mp[x][y] = %d\n", x, y, d, st, mp[x][y]); } bool check(void) { if (x == 1 && y == 1) { return true; } else { return false; } } bool isbody(int a, int b) { bx[0] = x; by[0] = y; //printf("x = %d, y = %d\n", bx[0], by[0]); for (int i = 1; i < l; ++i) { int dir = (st >> ((i - 1) * 2)) & 3; bx[i] = bx[i - 1] + dx[dir]; by[i] = by[i - 1] + dy[dir]; //printf("x = %d, y = %d\n", bx[i], by[i]); } //printf("...\n"); for (int i = 0; i < l; ++i) { if (bx[i] == a && by[i] == b) { return true; } } return false; } }; bool operator <(Node u, Node v) { return u.d + u.h > v.d + v.h; } int geth(int x, int y) { return abs(x - 1) + abs(y - 1); } int bfs(void) { priority_queue<Node> pq; Node u; clr(vis, 0); u.x = bx[0]; u.y = by[0]; u.st = 0; for (int i = 1; i < l; ++i) { int dir = getdir(bx[i - 1], by[i - 1], bx[i], by[i]); //printf("%d\n", dir); u.st |= (dir << (2 * (i - 1))); } u.isbody(1, 1); u.d = 0; vis[u.x][u.y][u.st] = 1; u.h = geth(u.x, u.y); pq.push(u); while (!pq.empty()) { u = pq.top(); pq.pop(); //u.output(); if (u.check()) { return u.d; } for (int i = 0; i < 4; ++i) { int nx = u.x + dx[i]; int ny = u.y + dy[i]; int nd = u.d + 1; int nst = ((u.st << 2) & ((1 << 14) - 1)) | ((i + 2) % 4); Node v = Node(nx, ny, nd, nst); if (nx < 1 || nx > n || ny < 1 || ny > m) { continue; } //v.output(); //printf("%d %d %d\n", nx, ny, v.isbody(nx, ny) ? 1 : 0); //printf("mp[%d][%d] = %d, %s, %d %d\n", nx, ny, mp[nx][ny], v.isbody(nx, ny) ? "yes" : "no", vis[nx][ny][nst], nst); if (mp[nx][ny] == 0 && !u.isbody(nx, ny) && !vis[nx][ny][nst]) { //printf("%d %d %d\n", nx, ny, 1); v.h = geth(nx, ny); pq.push(v); vis[nx][ny][nst] = 1; } } } return -1; } int main(int argc, char *argv[]) { int c = 0; while (scanf("%d%d%d", &n, &m, &l) != EOF) { if (!n && !m && !l) { break; } clr(mp, 0); for (int i = 0; i < l; ++i) { scanf("%d%d", &bx[i], &by[i]); } int k; scanf("%d", &k); for (int i = 0; i < k; ++i) { int nx, ny; scanf("%d%d", &nx, &ny); mp[nx][ny] = 1; } printf("Case %d: %d\n", ++c, bfs()); } return 0; }
poj 1475 Pushing Boxes
类似推箱子的游戏,一个人需要将一个箱子推到指定的地方,要求推箱子的步数最少,如果推箱子步数一样,那么,推箱子的步数和走的步数之和最少,如果还相等那么任何一个都行,要求输出具体方案。可以用一个4维数组来保存状态,每次判断可不可以推箱子就行了,可以加上启发式函数,启发式函数使用曼哈顿距离,因为要求推箱子的步数最少,所以,按照推箱子的步数排序,如果相同再按照总步数排序。
还有另一种方法是先bfs箱子,然后人在bfs,看能否推箱子到这个位置,速度比前面的方法快。
/************************************************************************* > File Name: 1324.cpp > Author: gwq > Mail: gwq5210@qq.com > Created Time: 2015年08月15日 星期六 21时45分46秒 ************************************************************************/ #include <cmath> #include <ctime> #include <cctype> #include <climits> #include <cstdio> #include <cstdlib> #include <cstring> #include <map> #include <set> #include <queue> #include <stack> #include <string> #include <vector> #include <sstream> #include <iostream> #include <algorithm> #define INF (INT_MAX / 10) #define clr(arr, val) memset(arr, val, sizeof(arr)) #define pb push_back #define sz(a) ((int)(a).size()) using namespace std; typedef set<int> si; typedef vector<int> vi; typedef map<int, int> mii; typedef pair<int, int> pii; typedef long long ll; const double esp = 1e-5; #define N 25 int mp , n, m, l, vis [1 << 14]; int dx[] = {-1, 0, 1, 0}; int dy[] = {0, 1, 0, -1}; int bx[10]; int by[10]; int getdir(int x, int y, int a, int b) { for (int i = 0; i < 4; ++i) { if (x + dx[i] == a && y + dy[i] == b) { return i; } } return -1; } struct Node { int x, y, d, st, h; Node () {} Node(int xx, int yy, int dd, int sst): x(xx), y(yy), d(dd), st(sst) {} void output(void) { printf("x = %d, y = %d, d = %d, st = %d, mp[x][y] = %d\n", x, y, d, st, mp[x][y]); } bool check(void) { if (x == 1 && y == 1) { return true; } else { return false; } } bool isbody(int a, int b) { bx[0] = x; by[0] = y; //printf("x = %d, y = %d\n", bx[0], by[0]); for (int i = 1; i < l; ++i) { int dir = (st >> ((i - 1) * 2)) & 3; bx[i] = bx[i - 1] + dx[dir]; by[i] = by[i - 1] + dy[dir]; //printf("x = %d, y = %d\n", bx[i], by[i]); } //printf("...\n"); for (int i = 0; i < l; ++i) { if (bx[i] == a && by[i] == b) { return true; } } return false; } }; bool operator <(Node u, Node v) { return u.d + u.h > v.d + v.h; } int geth(int x, int y) { return abs(x - 1) + abs(y - 1); } int bfs(void) { priority_queue<Node> pq; Node u; clr(vis, 0); u.x = bx[0]; u.y = by[0]; u.st = 0; for (int i = 1; i < l; ++i) { int dir = getdir(bx[i - 1], by[i - 1], bx[i], by[i]); //printf("%d\n", dir); u.st |= (dir << (2 * (i - 1))); } u.isbody(1, 1); u.d = 0; vis[u.x][u.y][u.st] = 1; u.h = geth(u.x, u.y); pq.push(u); while (!pq.empty()) { u = pq.top(); pq.pop(); //u.output(); if (u.check()) { return u.d; } for (int i = 0; i < 4; ++i) { int nx = u.x + dx[i]; int ny = u.y + dy[i]; int nd = u.d + 1; int nst = ((u.st << 2) & ((1 << 14) - 1)) | ((i + 2) % 4); Node v = Node(nx, ny, nd, nst); if (nx < 1 || nx > n || ny < 1 || ny > m) { continue; } //v.output(); //printf("%d %d %d\n", nx, ny, v.isbody(nx, ny) ? 1 : 0); //printf("mp[%d][%d] = %d, %s, %d %d\n", nx, ny, mp[nx][ny], v.isbody(nx, ny) ? "yes" : "no", vis[nx][ny][nst], nst); if (mp[nx][ny] == 0 && !u.isbody(nx, ny) && !vis[nx][ny][nst]) { //printf("%d %d %d\n", nx, ny, 1); v.h = geth(nx, ny); pq.push(v); vis[nx][ny][nst] = 1; } } } return -1; } int main(int argc, char *argv[]) { int c = 0; while (scanf("%d%d%d", &n, &m, &l) != EOF) { if (!n && !m && !l) { break; } clr(mp, 0); for (int i = 0; i < l; ++i) { scanf("%d%d", &bx[i], &by[i]); } int k; scanf("%d", &k); for (int i = 0; i < k; ++i) { int nx, ny; scanf("%d%d", &nx, &ny); mp[nx][ny] = 1; } printf("Case %d: %d\n", ++c, bfs()); } return 0; }
相关文章推荐
- 机器学习算法之:分类算法概述
- JSP编程技术笔试题
- 滑块控件UISlider
- SparkContext.setCheckpointDir()
- 知识小罗列
- Redis常用的命令(六)------集合类型
- 有向图深度优先与广度优先算法的C++实现
- UCOS II移植内容
- python __base__等内置方法
- Servlet和JSP学习指导与实践(一):Servlet API初探
- Servlet3.0注解配置Servlet和Filter
- JAVA程序员面试题
- Java中的异常(2)
- 如何给10^7个数据量的磁盘文件排序
- 最小生成树prim算法
- Android实战简易教程-第四十八枪(App引导页面效果实现)
- 分段控件UISegmentedControl
- 如何获得电脑的名称
- 二进制安全
- 字符串相关处理函数