数据结构实验1-2——2020
问题 A: 判断三角形形状
题目描述
给你三角形的三条边,你能告诉我它是哪种三角形吗?
如果是直角三角形,请输出“good”。如果是等腰三角形,请输出“perfect”。否则,请输出“just a triangle”。
题目保证输入数据合法。
输入
输入的第一行为一个整数t,表示测试样例的数量。
每组样例包含了三个整数a,b,c,代表了三角形的三条边的长度。(0<a,b,c<300)
输出
对于每组样例,输出结果,每组结果占一行。
样例输入
4
3 4 5
2 2 3
1 4 4
4 6 3
样例输出
good
perfect
perfect
just a triangle
代码
#include<iostream>
#include<algorithm>
using namespace std;
int triangle()
{
int a[3];
for(int i=0;i<3;i++)
cin>>a[i];
sort(a,a+3);
if(a[0]+a[1]>a[2])
{
if(a[0]*a[0]+a[1]*a[1]==a[2]*a[2])
cout<<"good"<<endl;
else if(a[0]==a[1]||a[1]==a[2])
cout<<"perfect"<<endl;
else cout<<"just a triangle"<<endl;
}
}
int main()
{
int n;
cin>>n;
for(int j=0;j<n;j++)
triangle();
return 0;
}
问题 B: 笨鸟先飞
题目描述
多多是一只小菜鸟,都说笨鸟先飞,多多也想来个菜鸟先飞。于是它从0点出发,一开始的飞行速度为1m/s,每过一个单位时间多多的飞行速度比上一个单位时间的飞行速度快2m/s,问n(0<n<10^5)个单位时间之后多多飞了多远?
输入
先输入一个整数T表示有几组数据。每组数据输入一个n,表示多多飞行的时间。
输出
输出多多飞行了多远,因为数字很大,所以对10000取模。
样例输入
2
1
2
样例输出
1
4
貌似就平方?
代码
#include<iostream>
using namespace std;
int prefly(int n)
{
int sum=0;
int p=1;
for(int i=0;i<n;i++)
{
sum=(sum+p)%10000;
p+=2;
}
return sum;
}
int main()
{
int t;
cin>>t;
int n;
for(int j=0;j<t;j++)
{
cin>>n;
cout<<prefly(n)<<endl;
}
}
问题 C: 火车出站
题目描述
铁路进行列车调度时,常把站台设计成栈式结构的站台,试问:
设有编号为1到n的n辆列车,顺序开入栈式结构的站台,则可能的出栈序列有多少种?
输入
输入包含多组测试数据。每组为一个正整数n(1<=n<=20),表示有n辆列车。
输出
输出可能的出栈序列有多少种。
样例输入
4
3
样例输出
14
5
可知满足递推式:h(n)=h(n-1)*(4*n-2)/(n+1);
代码
#include<iostream>
using namespace std;
long long out(long n)
{ if(n==1)
return 1;
else
return out(n-1)*(4*n-2)/(n+1);
}
int main()
{
long long t;
while(cin>>t)
cout<<out(t)<<endl;
}
问题 D: 最少的交换
题目描述
现在给你一个由n个互不相同的整数组成的序列,现在要求你任意交换相邻的两个数字,使序列成为升序序列,请问最少的交换次数是多少?
输入
输入包含多组测试数据。每组输入第一行是一个正整数n(n<500000),表示序列的长度,当n=0时。
接下来的n行,每行一个整数a[i](0<=a[i]<=999999999),表示序列中第i个元素。
输出
对于每组输入,输出使得所给序列升序的最少交换次数。
样例输入
5
9
1
0
5
4
3
1
2
3
0
样例输出
6
0
代码
#include <iostream>
using namespace std;
const int maxn = 500010;
int a[maxn];
int aux[maxn];
long long sum;
int n;
void merge(int l, int mid, int r) //归并排序
{
int i = l;//第一部分的排好序的
int end1 = mid;
int j = mid+1;//第二部分的排好序的
int end2 = r;
for (int t = l; t <= r; t++)
aux[t] = a[t];//将初始的数组a[]全部录入到aux[]中
for (int t = l; t <= r; t++)//从左往右遍历数组a[]
{
if (j > end2)//第二部分排好序的遍历完成,直接记录剩余的第一部分排好序的,移动次数不增加
a[t] = aux[i++];
else if (i > end1)//第一部分排好序的遍历完成,直接记录剩余的第二部分排好序的,移动次数不增加
a[t] = aux[j++];
else if (aux[i] > aux[j])//第一部分排好序的第一个元素>第二部分排好序的第一个元素
{
sum += mid+1-i;//移动的元素为a[j]到a[i](即aux[i])的位置,次数为j-i(即mid+1-i)
a[t] = aux[j++];
}
else if (aux[i] <= aux[j])//第一部分排好序的第一个元素<=第二部分排好序的第一个元素
a[t] = aux[i++];//记录到a[]中,i++,变为第一部分排好序的第二个元素
}
}
void msort(int l, int r)
{
if (l < r)
{
int mid = (l + r) / 2;
msort(l, mid);
msort(mid+1, r);
merge(l, mid, r);
}
}
int main(void)
{
while (cin >> n && n)
{
sum = 0;
for (int i = 0; i < n; i++)
cin >> a[i];
msort(0, n-1);
cout << sum << endl;
}
return 0;
}
//本地能运行,为啥oj上老是段错误?TAT
#include<iostream>
using namespace std;
int bubble(int a[],int time,int length)//返回交换次数
{
int p;
for(int j=0;j<length-1;j++)
for(int i=0;i<length-1-j;i++)
if(a[i]>a[i+1])
{
p=a[i];
a[i]=a[i+1];
a[i+1]=p;
time++;
}
return time;
}
int main()
{
int time=0; //time记录交换次数
int length=0;//length记录输入元素个数
int n;
int a[5000];
while(cin>>n&&n!=0)
{
length=n;
for(int i=0;i<n;i++)
cin>>a[i];
cout<<bubble(a,time,length)<<endl;
time=0;
length=0;
}
return 0;
}
问题 E: 欧几里得游戏
题目描述
小明和小红在玩欧几里得游戏。他们从两个自然数开始,第一个玩家小明,从两个数的较大数中减去较小数的尽可能大的正整数倍,只要差为非负即可。然后,第二个玩家小红,对得到的两个数进行同样的操作,然后又是小明。就这样轮流进行游戏,直至某个玩家将较大数减去较小数的某个倍数之后差为0为止,此时游戏结束,该玩家就是胜利者。
输入
输入包含多组测试数据。每组输入两个正整数,表示游戏一开始的两个数,游戏总是小明先开始。
当输入两个0的时候,输入结束。
输出
对于每组输入,输出最后的胜者,我们认为他们两个都是顶尖高手,每一步游戏都做出了最佳的选择。
具体输出格式见输出样例。
样例输入
34 12
15 24
0 0
样例输出
xiaoming wins
xiaohong wins
代码
#include<iostream>
using namespace std;
int main()
{
int a,b,k,t;
while(cin>>a>>b,a!=0||b!=0)
{
k=1;
if(a==b)
cout<<"xiaoming wins"<<endl;
else
{
while(a!=b)
{
if(a<b)//如果a<b,就交换ab值
{
t=a;
a=b;
b=t;
}
k++;
if(a/b!=1)
{
break;
}
a=a%b;
}
if(k%2==1)
cout<<"xiaohong wins"<<endl;
else
cout<<"xiaoming wins"<<endl;
}
}
return 0;
}
问题 F: 取石子游戏
题目描述
一天小明和小红在玩取石子游戏,游戏规则是这样的:
(1)本游戏是一个二人游戏;
(2)有一堆石子,共有n个;
(3)两人轮流进行;
(4)每走一步可以取走1~m个石子;
(5)最先取光石子的一方为胜。
如果游戏的双方使用的都是最优策略,请输出哪个人能赢。
输入
输入的第一行是一个正整数C(C<=100),表示有C组测试数据。
每组输入两个整数n和m(1<=n,m<=1000),n和m的含义见题目描述。
输出
对于每组输入,如果先走的人能赢,请输出“first”,否则请输出“second”。
样例输入
2
23 2
4 3
样例输出
first
second
代码
#include<iostream>
using namespace std;
int getstone(int n,int m)
{
if(n%(m+1)==0) return 0;
else return 1;
}
int main()
{
int c;
cin>>c;
int n,m;
for(int i=0;i<c;i++)
{
cin>>n>>m;
if(getstone(n,m))
cout<<"first"<<endl;
else
cout<<"second"<<endl;
}
}
问题 G: 奥运排序问题
题目描述
按要求,给国家进行排名。
输入
有多组数据。
第一行给出国家数N,要求排名的国家数M,国家号从0到N-1。
第二行开始的N行给定国家或地区的奥运金牌数,奖牌数,人口数(百万)。
接下来一行给出M个国家号。
输出
排序有4种方式: 金牌总数 奖牌总数 金牌人口比例 奖牌人口比例
对每个国家给出最佳排名排名方式 和 最终排名
格式为: 排名:排名方式
如果有相同的最终排名,则输出排名方式最小的那种排名,对于排名方式,金牌总数 < 奖牌总数 < 金牌人口比例 < 奖牌人口比例
如果有并列排名的情况,即如果出现金牌总数为 100,90,90,80.则排名为1,2,2,4.
每组数据后加一个空行。
样例输入
4 4
4 8 1
6 6 2
4 8 2
2 12 4
0 1 2 3
4 2
8 10 1
8 11 2
8 12 3
8 13 4
0 3
样例输出
1:3
1:1
2:1
1:2
1:1
1:1
提示
本题需要解决的是奥运会中各国家最有利的排名方式以及名次。只要进行五次排序即可。首先读入各国家信息,写好国家编号,计算和存储排名所需要的数据。然后按四种排名方式分别对需要排名的国家进行排名,并记录名次。最后使用国家编号对国家进行排名。这样就可以输出结果了。
第n次无耻地copy学长的代码 。
代码
#include<iostream>
using namespace std;
struct nation
{
int gold,medal;
double pop,gpp,mpp;
int rank1,rank2,rank3,rank4,highrank;
int rankmethod;
};
int main()
{
int n,m;
while(cin>>n>>m)
{
int b[m];
int x,y;
double z;
nation na[n];
for(int i=0;i<n;i++)
{
cin>>x>>y>>z;
na[i].gold=x;
na[i].medal=y;
na[i].pop=z;
na[i].gpp=x/z;
na[i].mpp=y/z;
}
for (int j=0;j<m;j++)
cin>>b[j];
for(int i=0;i<n;i++)
{
na[i].rank1=na[i].rank2=na[i].rank3=na[i].rank4=1;
for(int j=0;j<n;j++)
{
if(na[i].gold<na[j].gold)//gold排名
na[i].rank1++;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(na[i].medal<na[j].medal)//medal排名
na[i].rank2++;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(na[i].gpp<na[j].gpp)//gpp排名
na[i].rank3++;
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(na[i].mpp<na[j].mpp)//mpp排名
na[i].rank4++;
}
}
for(int i=0;i<n;i++)
{
na[i].highrank=na[i].rank1;
na[i].rankmethod=1;
if(na[i].highrank>na[i].rank2)
{
na[i].highrank=na[i].rank2;
na[i].rankmethod=2;
}
if(na[i].highrank>na[i].rank3)
{
na[i].highrank=na[i].rank3;
na[i].rankmethod=3;
}
if(na[i].highrank>na[i].rank4)
{
na[i].highrank=na[i].rank4;
na[i].rankmethod=4;
}
}
for(int i=0;i<m;i++)//取出b数组里需要排序的国家的序号,即b[i]
{
cout<<na[b[i]].highrank<<':'<<na[b[i]].rankmethod<<endl;
}
cout<<endl;
}
}
问题 H: 字符串的查找删除
题目描述
给定一个短字符串(不含空格),再给定若干字符串,在这些字符串中删除所含有的短字符串。
输入
输入只有1组数据。
输入一个短字符串(不含空格),再输入若干字符串直到文件结束为止。
输出
删除输入的短字符串(不区分大小写)并去掉空格,输出。
样例输入
in
#include
int main()
{
printf(" Hi ");
}
样例输出
#clude
tma()
{
prtf("Hi");
}
提示
注:将字符串中的In、IN、iN、in删除。
字符串这块儿学的不太好
代码
#include <string>
#include <iostream>
using namespace std;
int main()
{
string a,str;
getline(cin,a); //输入短字符串
for(int i = 0; i<a.size(); ++i)
{ //将a中字符串全部改为小写字母
a[i] = tolower(a[i]);
}
while(getline(cin,str))
{
string b = str,c = b; //将字符串保存至b,c,b将用于保存小写化后的字符,c保存原字符串
for(int i = 0; i<b.size(); ++i)
{ //将b中的字符全部改为小写,便于匹配
b[i] = tolower(b[i]);
}
int t = b.find(a,0); //在b串中查找a的位置,返回索引
while(t != string::npos) //查找成功,则重复循环
{
c.erase(t,a.size());
b.erase(t,a.size());
t = b.find(a,t); //从t位置为起点继续查找b中下一个出现字符串a的位置
}
t = c.find(' ',0);
while(t != string::npos)
{ //删除c中所有空格
c.erase(t,1);
t = c.find(' ',0);
}
cout<<c<<endl;
}
return 0;
}
问题 I: 后缀子串排序
题目描述
对于一个字符串,将其后缀子串进行排序,例如grain
其子串有:
grain
rain
ain
in
n
然后对各子串按字典顺序排序,即:
ain,grain,in,n,rain
输入
每个案例为一行字符串。
输出
将子串排序输出
样例输入
grain
banana
样例输出
ain
grain
in
n
rain
a
ana
anana
banana
na
nana
有空要补补这方面的知识
代码
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
bool cmp(string s1,string s2)//--以升序形式排列
{
return s1 < s2;
}
int main ()
{
int i,j;
char in[1000];//输入单词
string out[1000];//输出的数组,每个元素记录一个去掉一个字母的单词,未排序
//eg:输入grain,out[0]=grain,out[1]=rain
while(cin>>in)
{
int len=strlen(in);//计算in这个数组实际有字符的长度
for(i=0;i<len;i++)
{
string c="";//重新设一个string类型的变量来记录每个out[i]值
for(j=i;j<len;j++)
c+=in[j];
out[i]=c;
}
sort(out,out+len,cmp);//out+len不是out+1000
for(i=0;i<len;i++)
cout<<out[i]<<endl;
}
return 0;
}
问题 J: 算法:快速排序
题目描述
快速排序是对起泡排序的一种改进。它的基本思想是,通过一趟排序将待排序的记录分割成两个独立的部分,其中一部分记录的关键字均比另一部分的关键字小,在分成两个部分之后则可以分别对这两个部分继续进行排序,从而使整个序列有序。
快速排序的算法可以描述如下:
在本题中,读入一串整数,将其使用以上描述的快速排序的方法从小到大排序,并输出。
输入
输入的第一行包含1个正整数n,表示共有n个整数需要参与排序。其中n不超过100000。
第二行包含n个用空格隔开的正整数,表示n个需要排序的整数。
输出
只有1行,包含n个整数,表示从小到大排序完毕的所有整数。
请在每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
10
2 8 4 6 1 10 7 3 5 9
样例输出
1 2 3 4 5 6 7 8 9 10
提示
在本题中,需要按照题目描述中的算法完成快速排序的算法。
快速排序是一种十分常用的排序算法,其平均时间复杂度为O(knlnn),其中n为待排序序列中记录的个数,k为常数。大量的实际应用证明,在所有同数量级的此类排序算法中,快速排序的常数因子k是最小的,因此,就平均时间而言,快速排序是目前被认为最好的一种内部排序方法。
而在C语言的常用编译器中,qsort函数是一个非常常用的快速排序函数。
库函数直接搞定了,哈啊哈。
代码
//偷懒版
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n];
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
for(int i=0;i<n;i++)
cout<<a[i]<<' ';
cout<<endl;
}
//另一
#include <iostream>
using namespace std;
void Qsort(int arr[], int low, int high)
{
if (high <= low) return;
int i = low;
int j = high + 1;
int key = arr[low];
while (true)
{
/*从左向右找比key大的值*/
while (arr[++i] < key)
{
if (i == high){
break;
}
}
/*从右向左找比key小的值*/
while (arr[--j] > key)
{
if (j == low){
break;
}
}
if (i >= j) break;
/*交换i,j对应的值*/
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/*中枢值与j对应值交换*/
int temp = arr[low];
arr[low] = arr[j];
arr[j] = temp;
Qsort(arr, low, j - 1);
Qsort(arr, j + 1, high);
}
int main()
{
int num;
cin>>num;
int a[num];
for(int i=0;i<num;i++)cin>>a[i];
Qsort(a,0,num-1);/*这里原文第三个参数要减1否则内存越界*/
for(int i=0;i<num;i++)cout<<a[i]<<' ';
return 0;
}
问题 K: 为什么1024是程序员节
题目描述
小雏鸟正在看剧。突然被插播的广告吓了一跳。
只见广告上说 1024你懂的
小雏鸟不懂, 问身边的大白。大白说,这个1024是2的10次方,程序员把10月24日作为程序猿日。
现在给你一个整数N,让你求2的N次方有多大。
输入
一个整数N,N<30
输出
一个整数,2的N次方的结果
样例输入
10
样例输出
1024
pow函数不给过?
代码
#include<iostream>
using namespace std;
int main()
{
int n;
int sum=1;
cin>>n;
for(int i=0;i<n;i++)
sum*=2;
cout<<sum;
}