NEUQ2020-实验班-训练001(1-5题)
7-1 最短路径算法(Floyd-Warshall)
题目:
在带权有向图G中,求G中的任意一对顶点间的最短路径问题,也是十分常见的一种问题。
解决这个问题的一个方法是执行n次迪杰斯特拉算法,这样就可以求出每一对顶点间的最短路径,执行的时间复杂度为O(n3)。 而另一种算法是由弗洛伊德提出的,时间复杂度同样是O(n3),但算法的形式简单很多。
在本题中,读入一个有向图的带权邻接矩阵(即数组表示),建立有向图并使用Floyd算法求出每一对顶点间的最短路径长度。
输入格式:
输入的第一行包含1个正整数n,表示图中共有n个顶点。其中n不超过50。
以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。 当i和j相等的时候,保证对应的整数为0。
输出格式:
共有n行,每行有n个整数,表示源点至每一个顶点的最短路径长度。
如果不存在从源点至相应顶点的路径,输出-1。对于某个顶点到其本身的最短路径长度,输出0。
请在每个整数后输出一个空格,并请注意行尾输出换行。
输入样例:
4
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
输出样例:
0 3 2 1
6 0 4 7
2 5 0 3
3 6 1 0
题目分析:
简单的数据结构中的Floyd算法的实现与应用,只是本题需要注意的两个点是:1.在输入数据时,要将那些不相邻的邻点的权值由0变成inf。2.在输出数据时,应注意要将inf转为-1以后再输出。
算法思想:
Floyd-傻子也能看懂的弗洛伊德算法这个文章写的真心不错,大家阅读之后应该会有所收益。
具体AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int e[60][60];
int n;
int inf = 99999999;
cin>>n;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cin>>e[i][j];
if (i != j&&e[i][j]==0)
{
e[i][j] = inf;
}
}
}
for (int k = 1; k <= n; k++)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (e[i][j] > e[i][k] + e[k][j])
{
e[i][j] = e[i][k] + e[k][j];
}
}
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if(e[i][j]==inf)
{
e[i][j] = -1;
}
cout<<e[i][j]<<' ';
}
cout<<endl;
}
return 0;
}
7-2 栈的实现及基本操作
题目:
给定一个初始为空的栈和一系列压栈、弹栈操作,请编写程序输出每次弹栈的元素。栈的元素值均为整数。
输入格式:
输入第1行为1个正整数n,表示操作个数;接下来n行,每行表示一个操作,格式为1 d或0。1 d表示将整数d压栈,0表示弹栈。n不超过20000。
输出格式:
按顺序输出每次弹栈的元素,每个元素一行。若某弹栈操作不合法(如在栈空时弹栈),则对该操作输出invalid。
输入样例:
在这里给出一组输入。例如:
7
1 1
1 2
0
0
0
1 3
0
输出样例:
在这里给出相应的输出。例如:
2
1
invalid
3
思路:
只要记住栈的特点即可:先进后出,然后利用数组模拟上题所说的过程即可!
扩展资料:
AC代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[100000];
int n;
cin>>n;
int i=0;
while(n--)
{
int x;
cin>>x;
if(x==1)
{
int y;
cin>>y;
a[i] = y;
i++;
}
else if(x==0)
{
if(i-1<0)
{
cout<<"invalid"<<endl;
}
else
{
cout<<a[i-1]<<endl;
i--;
}
}
}
return 0;
}
7-3 队列的实现及基本操作
题目:
给定一个初始为空的队列和一系列入队、出队操作,请编写程序输出每次出队的元素。队列的元素值均为整数。
输入格式:
输入第1行为1个正整数n,表示操作个数;接下来n行,每行表示一个操作,格式为1 d或0。1 d表示将整数d入队,0表示出队。n不超过20000。
输出格式:
按顺序输出每次出队的元素,每个元素一行。若某出队操作不合法(如在队列空时出队),则对该操作输出invalid。
输入样例:
在这里给出一组输入。例如:
7
1 1
1 2
0
0
0
1 3
0
输出样例:
在这里给出相应的输出。例如:
1
2
invalid
3
**
思路:
与栈那个题一样,其实栈和队列都属于线性表的一部分,但不同的是,栈是先进后出,队列是先进先出,这个题可以用数组模拟普通队列过去,但建议大家可以尝试用一下循环队列去做这个题,因为循环队列可以更好的利用系统的空间。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int a[100000];
int n;
cin>>n;
int i=0;
int j=0;
while(n--)
{
int x;
cin>>x;
if(x==1)
{
int y;
cin>>y;
a[i] = y;
i++;
}
else if(x==0)
{
if(j-1>=i-1)
{
cout<<"invalid"<<endl;
}
else
{
cout<<a[j]<<endl;
j++;
}
}
}
return 0;
}
7-4 字符串的冒泡排序
题目:
我们已经知道了将N个整数按从小到大排序的冒泡排序法。本题要求将此方法用于字符串序列,并对任意给定的K(<N),输出扫描完第K遍后的中间结果序列。
输入格式:
输入在第1行中给出N和K(1≤K<N≤100),此后N行,每行包含一个长度不超过10的、仅由小写英文字母组成的非空字符串。
输出格式:
输出冒泡排序法扫描完第K遍后的中间结果序列,每行包含一个字符串。
输入样例:
6 2
best
cat
east
a
free
day
输出样例:
best
a
cat
day
east
free
思路:
直接把string类型看作int去做就可以,原理与数字的冒泡排序基本一致,只不过之前是定义整型数组,而现在该题是需要我们定义为字符串数组!
AC代码
#include<iostream>
using namespace std;
int main()
{
int n,k;
cin >> n >> k;
string s[101];
for(int i=0;i<n;i++)
{
cin>>s[i];
}
for(int i=0;i<k;i++)
{
for(int j=0;j<n-1;j++)
{
if(s[j]>s[j+1])
{
string t=s[j];
s[j]=s[j+1];
s[j+1]=t;
}
}
}
for(int i=0;i<n-1;i++)
{
cout<<s[i]<<endl;
}
cout<<s[n-1];
return 0;
}
7-5 打印选课学生名单
题目:
假设全校有最多40000名学生和最多2500门课程。现给出每个学生的选课清单,要求输出每门课的选课学生名单。
输入格式:
输入的第一行是两个正整数:N(≤40000),为全校学生总数;K(≤2500),为总课程数。此后N行,每行包括一个学生姓名(3个大写英文字母+1位数字)、一个正整数C(≤20)代表该生所选的课程门数、随后是C个课程编号。简单起见,课程从1到K编号。
输出格式:
顺序输出课程1到K的选课学生名单。格式为:对每一门课,首先在一行中输出课程编号和选课学生总数(之间用空格分隔),之后在第二行按字典序输出学生名单,每个学生名字占一行。
输入样例:
10 5
ZOE1 2 4 5
ANN0 3 5 2 1
BOB5 5 3 4 2 1 5
JOE4 1 2
JAY9 4 1 2 5 4
FRA8 3 4 2 5
DON2 2 4 5
AMY7 1 5
KAT3 3 5 4 2
LOR6 4 2 4 1 5
输出样例:
1 4
ANN0
BOB5
JAY9
LOR6
2 7
ANN0
BOB5
FRA8
JAY9
JOE4
KAT3
LOR6
3 1
BOB5
4 7
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1
5 9
AMY7
ANN0
BOB5
DON2
FRA8
JAY9
KAT3
LOR6
ZOE1
超时的思路:
定义一个结构体,包含学生的名字,选课数量,选课种类。
在输入数据的同时,定义一个数组,对每门课的数量进行统计,方便在后面输出
利用sort()函数,加上bool cmp()函数,使得结构体学生的姓名按照字典序进行排序,方便后续的输出
输出时,遍历每一个学生的每门课程,然后若有,则输出该学生的名字。
最后一个测试点超时的代码:
#include<bits/stdc++.h>
using namespace std;
struct Stu
{
string name;
int x;
int s[25];
};
bool cmp(Stu x,Stu y)
{
return x.name<y.name;
}
int main()
{
Stu a[40000];
int n,m;
cin>>n>>m;
int b[2500] = {0};
for(int i=0;i<n;i++)
{
cin>>a[i].name>>a[i].x;
for(int j= 0;j<a[i].x;j++)
{
cin>>a[i].s[j];
b[a[i].s[j]]++;
}
}
sort(a,a+n,cmp);
for(int i=1;i<=m;i++)
{
cout<<i<<" "<<b[i]<<endl;
for(int j = 0;j<n;j++)
{
for(int k = 0;k<a[j].x;k++)
{
if(a[j].s[k]==i)
{
cout<<a[j].name<<endl;
}
}
}
}
return 0;
}
宿舍大佬帮写的代码:
还没研究透,有兴趣的伙伴们可以看一下:
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
vector<string> st[maxn];
pair<string,vector<int>> stu[maxn];
int main() {
std::ios::sync_with_stdio(false);
cin.tie(0);
int n,k;
cin>>n>>k;
string name;
for(int i=1;i<=n;i++){
cin>>stu[i].first;
int nn;
cin>>nn;
while(nn--){
int x;
cin>>x;
stu[i].second.push_back(x);
}
}
sort(stu+1,stu+1+n);
for(int i=1;i<=n;i++){
for(auto ch:stu[i].second){
st[ch].push_back(stu[i].first);
}
}
for(int i=1;i<=k;i++){
cout<<i<<" "<<st[i].size()<<"\n";
for(auto ch:st[i]){
cout<<ch<<"\n";
}
}
return 0;
}
好了,就到这里了,欢迎大家和我进行讨论,虽然自己是个菜菜!