7-8 哈利·波特的考试
哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。
现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。
输入格式:
输入说明:输入第1行给出两个正整数N (≤100)和M,其中N是考试涉及的动物总数,M是用于直接变形的魔咒条数。为简单起见,我们将动物按1~N编号。随后M行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100),数字之间用空格分隔。
输出格式:
输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。
输入样例:
1 2 3 4 5 6 7 8 9 10 11 12 | 6 11 3 4 70 1 2 1 5 4 50 2 6 50 5 6 60 1 3 70 4 6 60 3 6 80 5 1 100 2 4 60 5 2 80 |
输出样例:
1 | 4 70 |
代码:
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <set> #include <queue> #define SIZE 105 int n,m; int G[SIZE][SIZE]={0}; int d[SIZE]={99999}; bool visited[SIZE]={false}; void Dijkstra(int start){ d[start]=0; for(int v=1;v<=n;v++){ int u=-1,INF=99999; for(int k=1;k<=n;k++){ if(visited[k]==false&&d[k]<INF){ u=k; INF=d[k]; } } if(u==-1)return; visited[u]=true; for(int k=1;k<=n;k++){ if(visited[k]==false&&G[u][k]>0&&d[u]+G[u][k]<d[k]){ d[k]=d[u]+G[u][k]; } } } } int main(){ int x,y,v,index=0; int MIN=99999; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&v); G[x][y]=v; G[y][x]=v; } for(int i=1;i<=n;i++){ for(int j=1;j<SIZE;j++){ d[j]=99999; visited[j]=false; } Dijkstra(i); // for(int j=1;j<=n;j++){ // printf("%d ",d[j]); // } // printf("\n"); int MAX=0; bool flag=false; for(int j=1;j<=n;j++){ if(d[j] == 99999){ flag=true; break; } if(d[j]>MAX){ MAX=d[j]; } } // printf("%d\n",MAX); if(flag==true){ continue; } if(MAX<MIN){ MIN=MAX; index=i; } } if(index == 0){ printf("0"); }else{ printf("%d %d",index,MIN); } return 0; }
总结:
1、定义数组 d[105] 数组的下标范围时0~104。若d[105]则指针溢出了,会报错。
2、注意无解的情况(如果只带1只动物是不可能完成所有变形要求的)
3、求最短路径的Dijkstra算法的写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | int n, G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数 int d[MAXV]; //起点到达各点的最短路径长度 bool vis[MAXV] = { false }; //标记数组,vis[i]==true表示已访问。初值均为false void Dijkstra( int s) //s为起点 { fill(d, d + MAXV, INF); //fill函数将整个d数组赋为INF d[s] = 0; //起点s到达自身的距离为0 for ( int i = 0; i < n; i++) //循环n次 { int u = -1, MIN = INF; //u使d[u]最小,MIN存放该最小的d[u] for ( int j = 0; j < n; j++) //找到未访问的顶点中d[]最小的 { if (vis[j] == false && d[j] < MIN) { u = j; MIN = d[j]; } } //找不到小于INF的d[u],说明剩下的顶点和起点s不连通 if (u == -1) return ; vis[u] = true ; //标记u为已访问 for ( int v = 0; v < n; v++) { //如果v未访问 && u能到达v && 以u为中介点可以使d[v]更优 if (vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]) { d[v] = d[u] + G[u][v]; //优化d[v] } } } } |
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现