基础实验8-1.2 直捣黄龙

题目链接
思路:1.使用哈希表将字符串转化为图的头结点的下标,并且在图的头结点中另外存储作为此点到起点的最短距离min_dis、最大杀敌数max_enemies、最长路径长max_len以及从起点出发到达此点的最多路径cnt的下标.
2.使用dijkstra算法求取最短路.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAX = 2e2 + 3;
const int INF = 0x7ffffff;
const int MIN = 0;
int cnt[MAX];
int num;
struct point {//邻接点
	char to[4];
	int dis;
	point(char* a, int b) { strcpy(to, a); dis = b; }
	point() {};
};
struct head {//头结点
	char from[4];
	int enemy;
	int pos;
	vector<point*>adjcent;
	head(char* a, int b, int c) { strcpy(from, a); enemy = b; pos = c; }
	head() {};
};
int Size, N;
int k;//头结点中存储下标
char pre[MAX][4];//前接点
int max_enemies[MAX];
int min_dis[MAX];
int max_len[MAX];
bool done[MAX];
point* Heap[MAX];//在堆排序时移动指针
vector<head*>e[MAX];//图
int find(int x);//寻找大于容量的第一个素数
int Hash_Table(char* tmp);//哈希
void Insert(point* tmp);//最小堆的插入
point* Delete();//从最小堆中删除并取得堆顶最小元素
void dijkstra(char* s, char* e);
bool cmp(point* A, point* B);
void init(char* s);
void print_path(char* end);//打印路径
head* find_pos(int hash, char* name);//根据哈希值找到头结点
int main() {
	int M;
	char tmp[4], tmp1[4];
	int enemy, dis;
	num = find(N);
	scanf("%d%d", &N, &M);
	char start[4], end[4];
	scanf("%s%s", start, end);
	int has = Hash_Table(start);
	head* H1 = new head(start, 0, k++);
	e[has].push_back(H1);
	for (int i = 0; i < N - 1; i++) {
		scanf("\n%s%d", tmp, &enemy);
		int hash = Hash_Table(tmp);
		head* H = new head(tmp, enemy, k++);
		e[hash].push_back(H);
	}
	for (int i = 0; i < M; i++) {
		scanf("\n%s%s%d", tmp, tmp1, &dis);
		head* H1 = find_pos(Hash_Table(tmp), tmp);
		head* H2 = find_pos(Hash_Table(tmp1), tmp1);
		point* t1 = new point(tmp1, dis);
		point* t2 = new point(tmp, dis);
		H1->adjcent.push_back(t1);
		H2->adjcent.push_back(t2);
	}
	dijkstra(start, end);
	print_path(end);
	int end_pos = find_pos(Hash_Table(end), end)->pos;
	printf("\n%d %d %d", cnt[end_pos], min_dis[end_pos], max_enemies[end_pos]);
}
int find(int x) {
	int i, j;
	for (i = x + 1;; i++) {
		for (j = 2; j <= sqrt(i); j++) {
			if (i % j == 0)
				break;
		}
		if (j == (int)sqrt(i) + 1)
			return i;
	}
}
int Hash_Table(char* tmp) {
	unsigned int seed = 31, sum = 0;
	while (*tmp) {
		sum = sum * 31 + (*tmp) - 'A';
		tmp++;
	}
	return (sum & 0x7fffffff) % num;
}
void Insert(point* tmp) {
	Size++;
	int i;
	for (i = Size; i != 1 && cmp(tmp, Heap[i / 2]); i /= 2)
		Heap[i] = Heap[i / 2];
	Heap[i] = tmp;
}
point* Delete() {
	point* Max = Heap[1];
	point* tmp = Heap[Size--];
	int parent, child;
	for (parent = 1; parent * 2 <= Size; parent = child) {
		child = parent * 2;
		if (child != Size && cmp(Heap[child + 1], Heap[child]))
			child++;
		if (cmp(Heap[child], tmp))
			Heap[parent] = Heap[child];
		else
			break;
	}
	Heap[parent] = tmp;
	return Max;
}
void dijkstra(char* s, char* e) {
	init(s);
	point* Head = new point{ s,0 };
	Insert(Head);
	while (Size) {
		point* tmp = Delete();
		head* T = find_pos(Hash_Table(tmp->to), tmp->to);
		if (done[T->pos])
			continue;
		done[T->pos] = true;
		int t = T->adjcent.size();
		for (int i = 0; i < t; i++) {
			point* Tmp = T->adjcent[i];
			head* V = find_pos(Hash_Table(Tmp->to), Tmp->to);
			if (done[V->pos])
				continue;
			if (min_dis[V->pos] > min_dis[T->pos] + Tmp->dis) {
				strcpy(pre[V->pos], T->from);
				cnt[V->pos] = cnt[T->pos];
				min_dis[V->pos] = min_dis[T->pos] + Tmp->dis;
				max_enemies[V->pos] = max_enemies[T->pos] + V->enemy;
				max_len[V->pos] = max_len[T->pos] + 1;
				point* TMP = new point(Tmp->to, min_dis[V->pos]);
				Insert(TMP);
			}
			else if (min_dis[V->pos] == min_dis[T->pos] + Tmp->dis) {
				cnt[V->pos] += cnt[T->pos];
				if (max_len[V->pos] < max_len[T->pos] + 1) {
					max_len[V->pos] = max_len[T->pos] + 1;
					max_enemies[V->pos] = max_enemies[T->pos] + V->enemy;
					strcpy(pre[V->pos], T->from);
				}
				else if (max_len[V->pos] == max_len[T->pos] + 1) {
					if (max_enemies[V->pos] < max_enemies[T->pos] + V->enemy) {
						max_enemies[V->pos] = max_enemies[T->pos] + V->enemy;
						strcpy(pre[V->pos], T->from);
					}
				}
			}

		}
	}
}
bool cmp(point* A, point* B) {
	return A->dis < B->dis;
}
void init(char* s) {
	head* H = find_pos(Hash_Table(s), s);
	for (int i = 0; i <= N; i++) {
		min_dis[i] = INF;
		max_len[i] = 0;
		max_enemies[i] = 0;
		done[i] = 0;
		cnt[i] = 0;
	}
	min_dis[H->pos] = 0;
	cnt[H->pos] = 1;
	strcpy(pre[H->pos], s);
}
head* find_pos(int hash, char* name) {
	int t = e[hash].size();
	for (int i = 0; i < t; i++)
		if (!strcmp(name, e[hash][i]->from))
			return e[hash][i];
}
void print_path(char* end) {
	head* H = find_pos(Hash_Table(end), end);
	if (!strcmp(pre[H->pos], end))
		printf("%s", end);
	else {
		print_path(pre[H->pos]);
		printf("->%s", end);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
直捣黄龙是一个经典的计算机实验,旨在让学生通过自己编写代码,了解计算机底层的运行原理。下面是一个简单的用C语言实现直捣黄龙实验的示例代码: ``` #include <stdio.h> #include <stdlib.h> int main() { int A = 1, B = 2, C = 3; // 初始化寄存器 int M[100] = {0}; // 初始化内存 int PC = 0; // 初始化程序计数器 int IR = 0; // 初始化指令寄存器 // 内存中存放直捣黄龙的指令 M[0] = 0x0102; // MOV A, #2 M[1] = 0x0203; // ADD A, #3 M[2] = 0x0211; // ADD A, B M[3] = 0x0322; // SUB C, #2 M[4] = 0x0412; // MOV B, A M[5] = 0x0500; // JMP 0 while (1) { IR = M[PC]; // 取指 PC++; // 更新程序计数器 int opcode = IR >> 8; // 取操作码 int operand = IR & 0xFF; // 取操作数 switch (opcode) { case 0x01: // MOV switch (operand) { case 0x12: // A, B A = B; break; case 0x13: // A, C A = C; break; default: A = operand; break; } break; case 0x02: // ADD switch (operand) { case 0x12: // A, B A += B; break; case 0x13: // A, C A += C; break; default: A += operand; break; } break; case 0x03: // SUB switch (operand) { case 0x12: // C, B C -= B; break; case 0x13: // C, A C -= A; break; default: C -= operand; break; } break; case 0x04: // MOV B = A; break; case 0x05: // JMP PC = operand; break; default: printf("Invalid opcode: %04x\n", opcode); exit(EXIT_FAILURE); } if (PC >= 6) { // 指令执行完毕,退出循环 break; } } printf("A = %d, B = %d, C = %d\n", A, B, C); // 输出寄存器的值 return 0; } ``` 以上代码实现了直捣黄龙的指令,可以在虚拟机中运行。虚拟机模拟了计算机的寄存器、内存、程序计数器和指令寄存器等重要组成部分。在循环中,每次取出指令并根据操作码和操作数执行相应的操作,直到程序执行完毕。最后,输出寄存器的值,即为直捣黄龙实验的结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值