HDU1044——Collect More Jewels,HDU1045——Fire Net,HDU1046——Gridland

目录

HDU1044——Collect More Jewels

题目描述

运行代码

代码思路

HDU1045——Fire Net

题目描述

运行代码

代码思路

HDU1046——Gridland

题目描述

运行代码

代码思路

HDU1044——Collect More Jewels

题目描述

Problem - 1044

运行代码

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f
#define Max 55
using namespace std;
string mapp[Max];
int w, h, l, m;
//l是时间限制 m是珠宝的数量
int val[Max];//宝石的价值 1-M
int used[Max][Max];//bfs时访问标记
int vis[Max];//dfs时访问
int step[Max][Max];
int ans;//结果
int sum;//所有宝石的价值总和
int dir[4][2] = { {-1,0},{1,0},{0,1},{0,-1} };
int dis[Max][Max];//记录初始位置,各宝石和出口两两间的距离
//从(x1,y1) 点到其他点的距离 s(0-m+1)是改点的标号,0表示初始位置
//m+1表示出口,1-m表示第i个宝物队
queue<int >q;
void bfs(int x1, int y1, int s) { //处理最短距离
	while (!q.empty())  q.pop();//必须要
	memset(used, 0, sizeof(used));
	memset(step, 0, sizeof(step));
	int u = x1 * w + y1;//二维转一维
	q.push(u);
	used[x1][y1] = 1;
	step[x1][y1] = 0;
	while (!q.empty()) {
		u = q.front();
		q.pop();
		int x = u / w;
		int y = u % w;
		for (int i = 0; i < 4; i++) {
			int xx = x + dir[i][0];
			int yy = y + dir[i][1];
			if (xx < 0 || xx >= h || yy < 0 || yy >= w)continue;
			if (used[xx][yy] || mapp[xx][yy] == '*') continue;
			used[xx][yy] = 1;
			step[xx][yy] = step[x][y] + 1;
			if (mapp[xx][yy] == '@') dis[s][0] = step[xx][yy];
			else if (mapp[xx][yy] == '<') dis[s][m + 1] = step[xx][yy];
			else if (mapp[xx][yy] >= 'A' && mapp[xx][yy] <= 'J')
				dis[s][mapp[xx][yy] - 'A' + 1] = step[xx][yy];
			q.push(xx * w + yy);
		}
	}
}
//dfs ,s表示当前点,value表示获得的价值,time表示花费的时间
void dfs(int s, int value, int time) {
	if (time > l) return;//剪枝
	if (ans == sum) return;
	if (s == m + 1) {//m+1代表出口 
		if (value > ans) ans = value;
		return;
	}
	for (int i = 0; i <= m + 1; i++) {
		if (dis[s][i] == 0 || vis[i]) continue;
		vis[i] = 1;
		dfs(i, value + val[i], time + dis[s][i]);
		vis[i] = 0;
	}
}
int main() {
	int t;
	cin >> t;
	for (int Case = 1; Case <= t; Case++) {
		memset(dis, 0, sizeof(dis));
		cin >> w >> h >> l >> m;
		sum = 0;
		ans = -1;
		for (int i = 1; i <= m; i++) {
			cin >> val[i];
			sum += val[i];
		}
		val[0] = val[m + 1] = 0;
		for (int i = 0; i < h; i++)
			cin >> mapp[i];
		for (int i = 0; i < h; i++) {
			for (int j = 0; j < w; j++) {
				if (mapp[i][j] == '@') bfs(i, j, 0);//起点到其他……的距离(时间)
				else if (mapp[i][j] == '<') bfs(i, j, m + 1);//终点到其他……的距离(时间) 
				else if (mapp[i][j] >= 'A' && mapp[i][j] <= 'J')
					bfs(i, j, mapp[i][j] - 'A' + 1);//宝藏到其他……的距离(时间)
			}
		}
		memset(vis, 0, sizeof(vis));
		vis[0] = 1;
		dfs(0, 0, 0);//0点是起点
		cout << "Case " << Case << ":" << endl;
		if (ans >= 0) cout << "The best score is " << ans << "." << endl;
		else cout << "Impossible" << endl;
		if (Case != t) cout << endl;
	}
	return 0;
}

代码思路

  1. 全局变量声明:

    • mapp[Max]:存储地图。
    • whlm:地图的宽度、高度、时间限制以及宝石的数量。
    • val[Max]:存储每个宝石的价值。
    • used[Max][Max]step[Max][Max]:在BFS中用于标记已访问的单元格并计算距离。
    • vis[Max]:在DFS中用于跟踪已访问的宝石。
    • ans:存储可达到的最大值。
    • sum:所有宝石价值的总和。
    • dir[4][2]:移动的方向(上、下、右、左)。
    • dis[Max][Max]:存储地图上各点之间的最短距离。
  2. BFS 函数 (bfs):

    • 此函数使用广度优先搜索(Breadth-First Search)来计算从给定点到地图上所有其他点的最短路径。
    • 它使用队列q来执行BFS。
    • 它更新dis矩阵以包含最短距离。
  3. DFS 函数 (dfs):

    • 此函数执行深度优先搜索(Depth-First Search),从当前点探索所有可能的路径。
    • 它检查当前路径是否能导致比当前最佳值(ans)更好的结果。
    • 它使用回溯法来探索所有可能的路径。
  4. 主函数 (main):

    • 读取输入数据,包括测试用例的数量t
    • 对于每个测试用例:读取地图尺寸、时间限制和宝石数量。读取宝石价值并初始化地图。从起始点、出口点以及每个宝石的位置执行BFS来计算最短路径。初始化vis并从起始点开始进行DFS以找到最优路径。输出当前测试用例的结果。

核心思想是预先计算出所有点对(起点、宝石、出口)之间的最短距离,使用BFS,然后使用DFS探索所有可能的宝石组合,这些组合可以在时间限制内被收集。DFS函数跟踪收集的总价值和所花费的时间,确保解决方案不超过时间限制。最终答案是在这些约束条件下可以达到的最高总价值。

HDU1045——Fire Net

题目描述

Problem - 1045

 

运行代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#define N 6
using namespace std;

char Map[N][N];
int flag[N];

int row[N][N], col[N][N], r[N], c[N];
int cnt_col, cnt_row;
bool path[N][N];

int DFS(int x) {
    for (int i = 0; i < cnt_col; i++) {
        if (!path[x][i] || flag[i])
            continue;
        flag[i] = 1;
        if (c[i] == -1 || DFS(c[i])) {
            c[i] = x;
            r[x] = i;
            return 1;
        }
    }
    return 0;
}

void Hungarian() {
    int ans = 0;
    memset(r, -1, sizeof(r));
    memset(c, -1, sizeof(c));
    for (int i = 0; i < cnt_row; i++) {
        if (r[i] == -1) {
            memset(flag, 0, sizeof(flag));
            ans += DFS(i);
        }
    }
    cout << ans << endl;
}

int main() {
    int n;
    while (scanf_s("%d%*c", &n) != EOF && n) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                Map[i][j] = getchar();
            }
            getchar();
        }

        memset(row, -1, sizeof(row));
        memset(col, -1, sizeof(col));
        cnt_row = cnt_col = 0;

        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (Map[i][j] == '.' && row[i][j] == -1) {
                    for (int k = j; Map[i][k] == '.' && k < n; k++)
                        row[i][k] = cnt_row;
                    cnt_row++;
                }

                if (Map[j][i] == '.' && col[j][i] == -1) {
                    for (int k = j; Map[k][i] == '.' && k < n; k++)
                        col[k][i] = cnt_col;
                    cnt_col++;
                }
            }
        }

        memset(path, false, sizeof(path));
        for (int i = 0; i < n; ++i)
            for (int j = 0; j < n; ++j)
                if (Map[i][j] == '.')
                    path[row[i][j]][col[i][j]] = true;

        Hungarian();

    }
    return 0;
}

代码思路

  1. 读取输入: 首先,程序读取一个整数n,表示棋盘的大小n x n。接下来,它读取棋盘的状态,其中.表示空位,而其他字符则表示障碍物或不可通行的位置。

  2. 构建行和列的索引: 接下来,程序遍历整个棋盘,对于每一行和每一列中的连续的.,它会分配一个索引,这将用于后续的匹配过程。例如,如果一行中有两个不相连的.序列,它们将分别被赋予不同的索引。

  3. 构建匹配图: 程序创建一个布尔矩阵path,其中path[i][j]为真表示第i个行索引和第j个列索引之间存在一个可以匹配的空位(即棋盘上的一个.)。这是通过遍历棋盘,如果遇到一个空位,则标记相应的行和列的索引间存在连接。

  4. 匈牙利算法实现: 使用匈牙利算法来找出最大匹配。匈牙利算法是一种在二分图中找到最大匹配的算法,这里的二分图是由行索引和列索引构成的。算法通过一系列深度优先搜索(DFS)尝试从行索引出发找到未匹配的列索引,形成匹配对。

  5. 执行匈牙利算法: 在Hungarian函数中,首先初始化rc数组来存储行和列的匹配情况。然后,对于每一个行索引,如果它没有匹配,就执行DFS函数来尝试找到一个匹配的列索引。DFS函数递归地尝试匹配,并返回一个布尔值表示是否成功找到匹配。如果成功,就更新rc数组来记录新的匹配关系,并增加匹配计数器ans

  6. 输出结果: 最后,输出ans作为最长的不相交的行与列匹配的数量。

HDU1046——Gridland

题目描述

Problem - 1046

运行代码

#include <iostream>
#include<iomanip>
using namespace std;

int main() {
    int n, a, b, i = 0;
    float temp = 0;
    cin >> n;
    while (n--) {
        i++;
        cin >> a >> b;
        temp = a * b;
        if (a % 2 != 0 && b % 2 != 0)
            temp = temp - 1 + 1.41;
        cout << "Scenario #" << i << ":" << endl;
        cout << fixed << setprecision(2) << temp << endl << endl;
    }
    return 0;
}

代码思路

  1. 初始化变量

    • n:存储用户输入的循环次数,也就是要处理多少组数据。
    • a 和 b:存储每组数据中的两个整数。
    • i:用于追踪当前处理的是哪一组数据,以便在输出中使用。
    • temp:用于存储每组数据的计算结果,类型为float,因为计算过程中可能会出现小数。
  2. 读取循环次数: 用户首先输入一个整数n,表示之后会有n组数据需要处理。

  3. 循环处理数据

    • 使用while循环,循环次数由n决定。
    • 在每次循环开始时,i增加1,用于标识当前处理的是第几组数据。
    • 接收用户输入的两个整数ab
    • 计算ab的乘积,并将结果存储在temp中。
  4. 条件判断:检查ab是否都是奇数(即a % 2 != 0b % 2 != 0)。如果是,那么在乘积的基础上减去1并加上1.41。

  5. 输出结果

    • 在输出之前,先使用cout打印出当前处理的是哪一组数据,格式为:"Scenario #" + 当前组数。
    • 使用fixedsetprecision(2)来设置输出的浮点数格式,保留两位小数。
    • 打印计算后的temp值。
    • 每组数据输出后,再输出两个换行符,使输出更加清晰易读。
  6. 结束:循环结束后,程序正常退出,返回0。

  • 33
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

筱姌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值