HDU 1026 (优先队列+BFS)

我现在怀疑我是不是高估自己的实力了……我可能比我想象的还要菜……

很普通的迷宫 很普通的迷宫中打怪兽

然后……WA了

好吧 其实在WA之前我想到了如果要打怪兽和绕路走哪个更快的问题 输出不是难事 那个紫书有我学到了

这个问题我思来想去没法自己干 然后百度了

结果还是WA了就很烦躁了有没有

总之还是AC了

唯一看的博客也没有细看 喵了个优先队列就回来了 

不是 有时候学了很多 但是当真正需要用的时候就未必想的到……我学的明明不多也想不到 菜……

有进步的 自己可以发现问题 虽然没有解决 自己可以独立打代码了 虽然喵了个优先队列 不是这输入法什么问题我也懒得改错字了 我明明平时也不卖萌啊 真是喵了个咪的

 

#include <iostream>
#include <string>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <cmath>
using namespace std;

struct node
{
	int x, y;
	int step;
	friend bool operator <(node a, node b)
	{
		return a.step > b.step;
	}
};

int n, m;
char mm[105][105];
int vis[105][105];
int step;
int mov[][2] = { 0,1,1,0,0,-1,-1,0 };
node p[1000][1000];
vector<node>v;

bool bfs()
{
	priority_queue<node>q;
	node t;
	t.x = 0; t.y = 0; t.step = 0;
	q.push(t);
	while (q.size())
	{
		t = q.top(); q.pop();
		if (t.x == n-1 && t.y == m-1)
		{
			break;
		}
		for (int i = 0; i < 4; i++)
		{
			node tt;
			tt.x = t.x + mov[i][0];
			tt.y = t.y + mov[i][1];
			if (tt.x < 0 || tt.x >= n || tt.y < 0 || tt.y >= m || vis[tt.x][tt.y])
				continue;
			if (mm[tt.x][tt.y] != 'X')
			{
				if (mm[tt.x][tt.y] != '.')
				{
					tt.step = t.step + mm[tt.x][tt.y] - '0';
					tt.step = tt.step + 1;
				}
				else
					tt.step = t.step + 1;
				q.push(tt);
				p[tt.x][tt.y] = t;
				vis[tt.x][tt.y] = 1;
			}
		}
	}
	if (t.x == n-1 && t.y == m-1)
	{
		node pp = p[n-1][m-1];
		while (!(pp.x == 0 && pp.y == 0))
		{
			v.push_back(pp);
			pp = p[pp.x][pp.y];
		}
		return true;
	}
	else
	{
		return false;
	}
}

void print()
{
	node t;
	t.x = 0; t.y = 0; t.step = 0;
	v.push_back(t);

	reverse(v.begin(), v.end());
	t.x = n - 1; t.y = m - 1; t.step = v[v.size() - 1].step + 1;
	v.push_back(t);

	int a;
	if (mm[n - 1][m - 1] != 'X' && mm[n - 1][m - 1] != '.')
	{
		a = v[v.size() - 1].step + mm[n - 1][m - 1] - '0';
	}
	else
	{
		a = v[v.size() - 1].step;
	}

	printf("It takes %d seconds to reach the target position, let me show you the way.\n", a);
	step = 1;
	for (int i = 1; i < v.size(); i++)
	{
		if (mm[v[i].x][v[i].y] != '.')
		{
			printf("%ds:(%d,%d)->(%d,%d)\n", step++, v[i - 1].x, v[i - 1].y, v[i].x, v[i].y);
			int cnt = mm[v[i].x][v[i].y] - '0';
			while (cnt--)
			{
				printf("%ds:FIGHT AT (%d,%d)\n",step++,v[i].x,v[i].y);
			}
		}
		else
			printf("%ds:(%d,%d)->(%d,%d)\n",step++,v[i-1].x,v[i-1].y,v[i].x,v[i].y);
	}
}

int main()
{
	while (cin >> n >> m)
	{
		v.clear();
		memset(vis, 0, sizeof(vis));
		for (int i = 0; i < n; i++)
			scanf("%s", mm[i]);

		if (bfs())
		{
			print();
		}
		else
			printf("God please help our poor hero.\n");
		puts("FINISH");
	}
	system("pause");
	return 0;
}

大致的方法就是 结构体 x y 保存坐标 step保存走了几步 如果该点为数字就加上数字 比较恼人的是终点可能有怪物(这点案例就给了还是比较良心的)起点有怪物的话应该可以判断 最后 最后还有一点就是时间 如果重点有怪物 就得多来几秒 所以计算要多少时间的时候得把终点的时间加上去

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于HDU4546问题,还可以使用优先队列(Priority Queue)来解决。以下是使用优先队列的解法思路: 1. 首先,将数组a进行排序,以便后续处理。 2. 创建一个优先队列(最小堆),用于存储组合之和的候选值。 3. 初始化优先队列,将初始情况(即前0个数的组合之和)加入队列。 4. 开始从1到n遍历数组a的元素,对于每个元素a[i],将当前队列中的所有候选值取出,分别加上a[i],然后再将加和的结果作为新的候选值加入队列。 5. 重复步骤4直到遍历完所有元素。 6. 当队列的大小超过k时,将队列中的最小值弹出。 7. 最后,队列中的所有候选值之和即为前k小的组合之和。 以下是使用优先队列解决HDU4546问题的代码示例: ```cpp #include <iostream> #include <vector> #include <queue> #include <functional> using namespace std; int main() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } sort(a.begin(), a.end()); // 对数组a进行排序 priority_queue<long long, vector<long long>, greater<long long>> pq; // 最小堆 pq.push(0); // 初始情况,前0个数的组合之和为0 for (int i = 0; i < n; i++) { long long num = pq.top(); // 取出当前队列中的最小值 pq.pop(); for (int j = i + 1; j <= n; j++) { pq.push(num + a[i]); // 将所有加和结果作为新的候选值加入队列 num += a[i]; } if (pq.size() > k) { pq.pop(); // 当队列大小超过k时,弹出最小值 } } long long sum = 0; while (!pq.empty()) { sum += pq.top(); // 求队列中所有候选值之和 pq.pop(); } cout << sum << endl; return 0; } ``` 使用优先队列的方法可以有效地找到前k小的组合之和,时间复杂度为O(nklog(k))。希望这个解法对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值