数据结构实验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;
}
posted @ 2020-06-04 13:05  繁辰一梦  阅读(908)  评论(0编辑  收藏  举报