c++写算法题:综合

本文通过一系列C++编程实例,详细介绍了最短路算法(Dijkstra与Floyd)和最小生成树算法(Kruskal与Prim),结合具体题目讲解了动态规划和深度优先搜索的应用,并强调了数组初始化的重要性。涵盖题目包括仙岛求药、四子连棋、过河卒、装箱问题等。
摘要由CSDN通过智能技术生成

拯救公主

百炼OJ, 题目链接
在这里插入图片描述
在这里插入图片描述
思路,典型的bfs问题,但需要处理的条件较多,此种题适合使用结构体来做,注意熟练使用结构体编程。
先贴上代码,以后再多写几遍,这里用到了状态压缩的方法记录宝石的数量。

#include <iostream>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
#define MAX 201
char a[MAX][MAX];

struct Node
{
   
    int x, y; //坐标。
    int num = 0; //存储宝石数目。
    int deep = 0; //搜索深度。
    Node() {
   
    }
    Node(int xx, int yy, int gg, int dd) : x(xx), y(yy), num(gg), deep(dd) {
   
    }
};

int dir[4][2] = {
   {
   0, -1},{
   -1, 0},{
   0, 1},{
   1, 0}};
int visited[MAX][MAX][1 << 5 - 1];   //宝石数目最大11111
int r, c, k, doorCount;
Node doors[11];

int bit1Count(int value) {
   
    unsigned int count = 0;
    while (value > 0) {
    // until all bits are zero
        if ((value & 1) == 1) // check lower bit
            count++;
        value >>= 1; // shift bits, removing lower bit
    }
    return count;
}

void printQueue(std::queue<Node> q) {
   
    while (!q.empty()) {
   
        Node node = q.front();
        q.pop();
        cout << "(" << node.x << ", " << node.y << ", "
            << bit1Count(node.num) << ", " << node.deep << ") ";
    }
    cout << endl << endl;
}

int getTarget(Node* node, Node* endNode) {
   
    return (node->x == endNode->x && node->y == endNode->y && bit1Count(node->num) >= k);
}

int bfs(Node* startNode, Node* endNode) {
   
    if (startNode == NULL || endNode == NULL) return -1;
    memset(visited, 0, sizeof(visited));
    visited[startNode->x][startNode->y][0] = 1; //置起点已经访问
    queue<Node> q;
    q.push(*startNode); //起点入队
    while (!q.empty()) {
   
        Node node = q.front(); //取队首元素,出队
        q.pop();
        for (int i = 0; i < 4; i++) {
     // 遍历四个方向
            int newX = node.x + dir[i][0];
            int newY = node.y + dir[i][1];
            if (newX < 0 || newX >= r || newY < 0 || newY >= c) continue;  // 越界则下一个
            if (a[newX][newY] == '#' || visited[newX][newY][node.num]==1) continue; //碰到墙或者已经访问过,则下一个
            //不是墙壁并且此节点没访问过
            visited[newX][newY][node.num] = 1;
			// 当前路可走
            Node newNode(newX, newY, node.num, node.deep + 1);
            if (a[newX][newY] >= '0' && a[newX][newY] <= '4') {
    // 遇到宝石
                newNode.num |= 1 << (a[newX][newY] - '0');  //状态压缩记录宝石数量
            }
            if ((newNode.x == endNode->x && newNode.y == endNode->y && bit1Count(newNode.num) >= k)) {
   
                return newNode.deep;
            }
            // 没有达到终点,则当前点入队
            q.push(newNode);

            //如果是传送门的话就将所有其它传送门也加入搜索队列。
            if (a[newX][newY] == '$') {
   
                for (int j = 0; j < doorCount; j++) {
   
                    Node currNode = doors[j];
                    if (currNode.x == newX && currNode.y == newY) continue;
                    Node doorNode(currNode.x, currNode.y, newNode.num, newNode.deep);
                    q.push(doorNode);
                }
            }
        }
      
    }
    return -1;
}

int main() {
   
    int t;
    cin >> t; //t组数据
    while (t--) {
   
    	// Node记录坐标,宝石数目,深度
        Node *startNode = NULL, *endNode = NULL;
        cin >> r >> c >> k; //r*c矩阵,k个宝石
        doorCount = 0;
        for (int i = 0; i < r; i++) {
   
            for (int j = 0; j < c; j++) {
   
                cin >> a[i][j];
                switch (a[i][j]) {
   
                case '$':  //记录所有传送门的位置。
                    doors[doorCount++] = Node(i, j, 0, 0);
                    break;
                case 'S':  // 记录起点位置
                    startNode = new Node(i, j, 0, 0);
                    break;
                case 'E':   // 记录终点位置
                    endNode = new Node(i, j, 0, 0);
                }
            }
        }
        int ans=bfs(startNode, endNode);
        ans == -1 ? (cout << "oop!" << endl) : (cout << ans << endl);
    }
    return 0;
}
#include <iostream>
#include <unordered_map>
#include <vector>
#include <queue>
using namespace std;
//16.57
struct Node{
   
	int x,y;  // 坐标
	int num; // 宝石个数
	int depth;  // 深度
	
	Node(){
   
	}
	Node(int xx,int yy,int nn,int dd) :x(xx),y(yy),num(nn),depth(dd) {
   }
};
int R,C,K,ct=0;
//vector<vector<char>> a(R,vector<char>(C));
char a[200][200];
int dx[]={
   -1,1,0,0}; //上下左右
int dy[]={
   0,0,-1,1};
Node jewelNode[11];

int visited[200][200][1 << 5 - 1];   //宝石数目最大11111

int bit1Count(int value) {
   
    unsigned int count = 0;
    while (value > 0) {
    // until all bits are zero
        if ((value & 1) == 1) // check lower bit
            count++;
        value >>= 1; // shift bits, removing lower bit
    }
    return count;
}

int bfs(Node *startNode,Node *endNode){
   
	// 把startNode加入队列
	visited[startNode->x][startNode->y][0] = 1; //置起点已经访问
	queue<Node> q;  // queue<Node*> q行不行?
	q.push(*startNode); //起点入队 q.push(startNode)?
	while(!q.empty()){
   
		Node node=q.front();q.pop();  // 取队首元素,出队
		// 对四个方向遍历
		for(int i=0;i<4;i++){
   
			int newx=node.x+dx[i];
			int newy=node.y+dy[i];
			// 越界或者已经访问则跳过--------------visited数组为什么是三维的: 包含了宝石的情况
			if(newx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值