hdu 1026 好题 优先队列+递归输出
这个就是基于优先队列的bfs,采用优先队列适用于这种耗时不为1的情况。
至于递归输出,之前也碰到过一次,这种思路真的很巧妙,但让我自己写容易写假,感觉理解的还不是很透彻。
// Problem: Ignatius and the Princess I
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1026
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
int n, m;
struct node
{
int x, y, t;
friend bool operator<(node a, node b)
{
return a.t > b.t;
}
};
const int N = 105;
char a[N][N];
int vis[N][N];
int flag[N][N];
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool ok(int x, int y)
{
if (x < 0 || y < 0 || x >= n || y >= m || a[x][y] == 'X')
return false;
return true;
}
int bfs()
{
int count = 0;
memset(vis, 0, sizeof(vis));
memset(flag, 0, sizeof(flag));
struct node cur, nex;
cur.x = 0, cur.y = 0;
vis[cur.x][cur.y] = 1;
cur.t = 0;
priority_queue<node> qu;
qu.push(cur);
while (!qu.empty())
{
cur = qu.top();
qu.pop();
// printf("%d %d%d\n", cur.t, cur.x, cur.y);
if (cur.x == n - 1 && cur.y == m - 1)
{
return cur.t;
}
for (int i = 0; i < 4; i++)
{
nex.x = cur.x + dir[i][0];
nex.y = cur.y + dir[i][1];
if (ok(nex.x, nex.y) && !vis[nex.x][nex.y])
{
flag[nex.x][nex.y] = i;
if (a[nex.x][nex.y] <= '9' && a[nex.x][nex.y] >= '1')
{
nex.t = cur.t + a[nex.x][nex.y] - '0' + 1;
}
else
nex.t = cur.t + 1;
vis[nex.x][nex.y] = 1;
qu.push(nex);
}
}
}
return -1;
}
int cnt;
void show(int x, int y)
{
if (x == 0 && y == 0)
{
return;
}
int prex = x - dir[flag[x][y]][0];
int prey = y - dir[flag[x][y]][1];
show(prex, prey);
printf("%ds:(%d,%d)->(%d,%d)\n", cnt++, prex, prey, x, y);
if (a[x][y] >= '1' && a[x][y] <= '9')
{
for (int i = 1; i <= a[x][y] - '0'; i++)
printf("%ds:FIGHT AT (%d,%d)\n", cnt++, x, y);
}
}
int main()
{
while (cin >> n >> m)
{
cnt = 1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> a[i][j];
}
}
int ans = bfs();
if (ans == -1)
puts("God please help our poor hero.");
else
{
printf("It takes %d seconds to reach the target position, let me show you the way.\n", ans);
show(n - 1, m - 1);
}
puts("FINISH");
}
}
hdu 1026
这题的话就是常规bfs就行,因为每一步耗时都是1s,但是要注意的是剪枝,对于bfs来说最有效的剪枝不就是打标记嘛,目的是不走回头路,但是对于这题来说,有时候可能会出现不得不走回头路的情况,所以只能在炸弹重启装置处打标记。
// Problem: Nightmare
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1072
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
int a[10][10];
int sx, sy;
int fx, fy;
int n, m;
int vis[10][10];
int cnt;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct node
{
int step;
int x, y, t;
};
bool ok(int x, int y)
{
if (x < 1 || y < 1 || x > n || y > m || a[x][y] == 0)
return false;
return true;
}
void bfs()
{
memset(vis, 0, sizeof(vis));
struct node cur, nex;
cur.step = 0;
cur.x = sx, cur.y = sy, cur.t = 6;
vis[cur.x][cur.y] = 1;
queue<node> qu;
qu.push(cur);
while (!qu.empty())
{
cur = qu.front();
qu.pop();
if (cur.x == fx && cur.y == fy)
{
printf("%d\n", cur.step);
return;
}
for (int i = 0; i < 4; i++)
{
nex.x = cur.x + dir[i][0];
nex.y = cur.y + dir[i][1];
nex.t = cur.t - 1;
if (ok(nex.x, nex.y) && !vis[nex.x][nex.y] && nex.t > 0)
{
if (a[nex.x][nex.y] == 4)
{
nex.t = 6;
vis[nex.x][nex.y] = 1;
}
nex.step = cur.step + 1;
qu.push(nex);
}
}
}
printf("-1\n");
return;
}
int main()
{
int t;
cin >> t;
while (t--)
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
if (a[i][j] == 2)
{
sx = i, sy = j;
}
if (a[i][j] == 3)
{
fx = i, fy = j;
}
}
}
bfs();
}
}
hdu 1242
这题是优先队列bfs的裸题,没什么说的
// Problem: Rescue
// Contest: HDOJ
// URL: http://acm.hdu.edu.cn/showproblem.php?pid=1242
// Memory Limit: 65 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
const int N = 205;
char a[N][N];
int vis[N][N];
int n, m;
int sx, sy, fx, fy;
int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
struct node
{
int x, y, t;
friend bool operator<(node a, node b)
{
return a.t > b.t;
}
};
bool ok(int x, int y)
{
if (x < 1 || x > n || y < 1 || y > m || a[x][y] == '#')
return false;
return true;
}
void bfs()
{
memset(vis, 0, sizeof(vis));
priority_queue<node> qu;
struct node cur, nex;
cur.x = sx, cur.y = sy;
cur.t = 0;
vis[cur.x][cur.y] = 1;
qu.push(cur);
while (!qu.empty())
{
cur = qu.top();
qu.pop();
if (cur.x == fx && cur.y == fy)
{
printf("%d\n", cur.t);
return;
}
for (int i = 0; i < 4; i++)
{
nex.x = cur.x + dir[i][0];
nex.y = cur.y + dir[i][1];
if (ok(nex.x, nex.y) && !vis[nex.x][nex.y])
{
if (a[nex.x][nex.y] == 'x')
{
nex.t = cur.t + 2;
}
else
nex.t = cur.t + 1;
vis[nex.x][nex.y] = 1;
qu.push(nex);
}
}
}
puts("Poor ANGEL has to stay in the prison all his life.");
return;
}
int main()
{
while (cin >> n >> m)
{
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
if (a[i][j] == 'a')
{
fx = i;
fy = j;
}
if (a[i][j] == 'r')
{
sx = i;
sy = j;
}
}
}
bfs();
}
}
其实这些是我很久以前写的题了,当时没写题解
今天我只学了一个离散化,离散化是一种小技巧,对于很大的数据而言,用数组下标可能无法表示,所以采用离散化,把他们的相对关系用下标来表示。
//首先定义一个a 结构体
struct node a {
int val;
int order;
};
sort(a+1,a+1+n,cmp)//以val升序排列
b[a[1].order]=1;
for(int i=2,int count=1;i<=n;i++)
{
if(a[i].val==a[i-1].val)
b[a[i].order]=count;
else
b[a[i].order]=++count;
}
看着蛮抽象,其实弄几个数过一下就理解了,反正就是用较小的count替换了大数val