2021东华oj复试(最后一周题库)

因为公布时间是3月22日至3月29日,就为了及时总结复习,我用typora把部分题目总结到一起了,代码均可AC。由于此次只要求使用C++写(哭死,事前没用过C++,还好没涉及到类和对象),故均为C++代码。

2 黑色星期五

#include<iostream>

using namespace std;

int main()
{
    int n;
    int a[12]={31,28,31,30,31,30,31,31,30,31,30,31};
    //int week[7]=[0,1,2,3,4,5,6];
    while(scanf("%d",&n)!=EOF)
    {
        int day=0;
        for(int i=1998;i<n;i++)
        {
            if((i%4==0&&i%100!=0)||(i%400==0))
                day+=366;
            else
                day+=365;
        }
        int date=(day+4)%7;//计算输入的该年第一天是星期几
        int num=0;
        if((n%4==0&&n%100!=0)||(n%400==0))//判断该年是否为闰年
            a[1]++;
        for(int i=0;i<12;i++)
        {
            if((date+12)%7==5)//判断每个月13号是否为星期五
                num++;
            date=date+a[i];
        }
        printf("%d\n",num);
    }
}

3整除的尾数

#include <stdio.h>

int getResult(int a, int b, int weishu[])

{

    int k=0;
    for(int i=0; i<100; i++)//在末尾添加二位数
    {
            int t=a*100+i;
        if(t%b==0)
        {
            weishu[k++]=i;
        }

    }
    return k;
}

int main()

{

    int a, b, weishu[100],count,i;

    scanf("%d%d", &a, &b);

    count=getResult(a,b,weishu);

    for(i=0; i<count; i++)

    {

        if (i>0)

            printf(" ");

        printf("%02d", weishu[i]);

    }

    printf("\n");

    return 0;

}

4 谁是老二

#include<iostream>
 using namespace std;
 int main()
 {
     int n;

     while(cin>>n)
     {
         int a[n];
         int b[n];
         int secondmax;
         int flag=0;
         for(int i=0;i<n;i++)
         {
             cin>>a[i];
             b[i]=a[i];
         }
         int max=0;
         for(int i=0;i<n;i++)//对数组进行排序
         {
             for(int j=i;j<n;j++)
             {
                 if(b[i]>b[j])
                 {
                     int temp=b[i];
                     b[i]=b[j];
                     b[j]=temp;
                 }
             }
         }
         for(int i=n-2;i>0;i--)
         {
             if(b[n-1]>b[i])
             {
                 secondmax=b[i];//找出第二大
                 break;
             }
             if(i==1)
                flag=1;
         }
         if(flag)
        cout<<"none"<<endl;
        else
        {
            cout<<secondmax;
            for(int i=0;i<n;i++)
         {
             if(a[i]==secondmax)//输出第二大下标位置
                cout<<" "<<i;
         }
         cout<<endl;
        }



     }
 }

8n层正方形

#include<stdio.h>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int a[2*n-1][2*n-1];
        int k=1;
        while(k<=n)
        {
            for(int i=k-1; i<=(2*n-1)-k; i++)//二维数组的两端开始向里收缩
                for(int j=k-1; j<=(2*n-1)-k; j++)
                    a[i][j]=k;//不断覆盖外层的赋值,把所在圈数填充完好
            k++;
        }
        for(int i=0;i<(2*n-1);i++)
        {
            for(int j=0;j<(2*n-1);j++)
            {
                if(j<2*n-2)
                printf("%d ",a[i][j]);
                else
                    printf("%d",a[i][j]);
            }
            printf("\n");
            
        }

    }
}

小数第n 位

#include<iostream>
#include<vector>

using namespace std;

typedef long long ll;

int main(){
	ll a;
	ll b;
	int n;
	cin>>a>>b>>n;
	while(n - 8 > 0){ //快速减小n,逼近第n位
		a *= 1e8; //不能*的太大,否则会溢出
		a %= b;
		n -= 8;
	}
	for(int i = 0;i < n + 2;i++){
		a *= 10;//①因为之前是对b取余得到的,所以此时的a一定小于吧,对a*10,在对b取余可获得一位数
		if(i >= n - 1){ //开始输出三个位
			cout<<a/b;
		}
		a %= b;
	}
	return 0;
}

34 数列

#include<cmath>
#include<iostream>
#include<cstdio>
using namespace std;
long long a[100000];
int n,m,k=1,t;
int main()
{
    a[0]=0;
    while(cin>>m>>n)
    {
        //scanf("%d%d",&m,&n);
        for(int i=0; i<100; i++)
        {
            t=k;
            for(int j=0; j<t; j++)
            {
                a[k]=pow(m,i)+a[j];//每个轮回,都要把pow(m,i)加上去,同时,使用前面已经存在的每个数
                if(k==n)
                {
                    cout<<a[k]<<endl;
                    return 0;
                }
                else
                {
                    k++;
                }
            }
        }
    }

    return 0;
}


35 孪生素数

解法:找出不大于N 的所有素数,存储在一维数组中。遍历一位数组,若该素数和后面一位素数之间相差为2,则孪生素数对加一。

输出孪生素数对即可。

36 集合运算

解法:对集合A,B分别进行排序。从小到大进行遍历,两个下标逐渐增加,当A和B中共有时,记录在交集中。把数组B放在数组A中,进行排序,若相同只输出一个,即为并集。遍历数组A,对比在数组B中的每个数,若没有,则输出。

37 区间k 大数查询

解法:根据输入的起始位置,确定截取区间,按照从大到小进行排序,第k大数即为第k-1下标位置上的数。

38 明明的随机数

解法:输入要随机选择的个数N,从大数组中选出N个数,按照从小到大进行排序,输出时,若相同,则只输出一个。

39 数的统计

解法:对于输入的数组,对不同的数字记录下来,排序,依次统计出现的次数

#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
    return a<b;
}
typedef struct arr
{
    int num;
    int count;
};
int main()
{
    int n;
    while(cin>>n)
    {
        int beginArr[n];
        struct arr arrnum[n];
        int k;
        for(int i=0; i<n; i++)
        {
            arrnum[i].count=0;
            arrnum[i].num=0;
        }

        for(int i=0; i<n; i++)
        {
            cin>>beginArr[i];
        }
        sort(beginArr,beginArr+n);
        arrnum[0].num=beginArr[0];
        arrnum[0].count++;
        k=0;
        for(int i=1; i<n; i++)
        {
            if(beginArr[i]==beginArr[i-1])
            {
                arrnum[k].count++;
            }
            else
            {
                k++;
                arrnum[k].num=beginArr[i];
                arrnum[k].count++;
            }
        }
        for(int i=0; i<=k; i++)
        {
            cout<<arrnum[i].num<<" "<<arrnum[i].count<<endl;
        }
    }
}

40 数字黑洞

解法:若不为6174,则计算出四位数的最大值,最小值,差,然后比较是否为6174,若否,次数加一,循环上述过程。

//每次把number中的各个位置上的数字分解到temp中,排序之后,通过遍历来构成max和min,max-min来构造新的number
#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,i,count=0;
	while(cin>>n)
    {
      int num=n;
	while(num!=6174)
	{
		i=0;
		int max=0,min=0;
		int number=num;
		int temp[4];
		memset(temp,0,sizeof(temp));
		while(number)
		{
			temp[i++]=number%10;
			number=number/10;
		}
		sort(temp,temp+4);
		for(int j=0;j<4;j++)
		{
			max=max*10+temp[4-j-1];
			min=min*10+temp[j];
		}
		num=max-min;
		count++;
	}
	cout<<count<<endl;  
    }
	
	return 0;
}

41 质数的乘积

解法:求出前n个质数,对其进行乘积运算,并对50000进行取模

#include<bits/stdc++.h>
using namespace std;
int prime(long n)
{
    if(n==1)
        return 0;
    if(n==2||n==3)
        return 1;
    long t=sqrt(n);
    for(long i=2; i<=t; i++)
    {
        if(n%i==0)
            return 0;
    }
    return 1;
}
int main()
{
    long long n;
    while(cin>>n)
    {
        long long sum=1;
        for(long long i=2;; i++)
        {
            if(prime(i))
            {
                sum=sum*i;
                sum=sum%50000;
                n--;
            }
            if(n==0)
                break;


        }
        cout<<sum<<endl;

    }

    return 0;
}

42暗恋

解法:对于输入的二维数组,遍历每个节点,判断由该节点生成的爱情指标的最大值,最后输出最大值。

#include<bits/stdc++.h>
using namespace std;
int love[201][201] = { 0 };
bool isLove(int x, int y,int len)
{
    int color = love[x][y];
    x++;
    y++;
    if (love[x][y] != color) return false;
    for (int i = 1; i <= len; i++)//判断正方形内是否全部为同一颜色
    {
        if (love[x - i][y] != color) return false;//y列检查
        if (love[x][y - i] != color) return false;//x行检查
    }
    return true;
}
int main()
{
    int r, c;
    cin >> r >> c;
    for (int i = 1; i <= r; i++)
    {
        for (int j = 1; j <= c; j++)
        {
            cin >> love[i][j];
        }
    }
    int max = 1;
    bool flag = 0;
    for (int i = 1; i <= r; i++)
    {
        for (int j = 1; j <= c; j++)
        {
            if (r - i < max)//剩余高度小于最大边长跳出
            {
                flag = 1;
                break;
            }
            if (c - j < max)//剩余宽度小于最大边长 换行
            {
                continue;
            }
            //判断最大边长
            int len = 1, x = i, y = j;
            while (x < r&&y < c)
            {
                if (isLove(x, y,len))
                {
                    x++, y++, len++;
                    if (len>max) max = len;
                }
                else
                {
                    break;
                }
            }
        }
        if (flag)
            break;
    }
    cout << max*max<< endl;
    return 0;
}

43 扫雷

解法:对于输入的二位字符型数组,遍历数组。对于安全区,比较周围最多八个数,判断是否有地雷,若有则记录个数。对于雷区,不比较。

#include<bits/stdc++.h>
using namespace std;
char a[100][100];
int m,n;
void bb(int i,int j)
{
    int sum=0,x=i-1,y=j-1,x1=i+1,y1=j+1,i1,j1;
    if(a[i][j]=='*')
    {
       cout<<"*";
    }
    else
    {
        if(i==0)//判断边界
        {
            x=0;
        }
        if(j==0)
        {
            y=0;
        }
        if(i==m-1)
        {
            x1=m-1;
        }
        if(j==n-1)
        {
            y1=n-1;
        }
        for(i1=x; i1<=x1; i1++)//若该点非边界点,判断其周围八个点地雷的个数
        {
            for(j1=y; j1<=y1; j1++)
            {
                if(a[i1][j1]=='*')
                {
                    sum++;
                }
            }
        }
        cout<<sum;
    }
}
int main()
{
    int i,j,count=0;
    char x;
    while(1)
    {
        cin>>m>>n;
        if(m==0&&n==0)
        {
            break;
        }
        count++;
        for(i=0; i<m; i++)
        {
            for(j=0; j<n; j++)
            {
                cin>>x;
                if(x==10)//遇到换行,保持j不越界
                {
                   j--;
                }
                if(x!=10)
                {
                    a[i][j]=x;
                }
            }
        }
        cout<<"Field #"<<count<<endl;
        for(i=0; i<m; i++)
        {
            for(j=0; j<n; j++)
            {
                bb(i,j);
            }
            cout<<endl;
        }
        cout<<endl;
    }
    return 0;
}


44矩阵乘方

解法:给定一个矩阵A,一个非负整数b和一个正整数m,求A的b次方除m的余数。
  其中一个nxn的矩阵除m的余数得到的仍是一个nxn的矩阵,这个矩阵的每一个元素是原矩阵对应位置上的数除m的余数。
  要计算这个问题,可以将A连乘b次,每次都对m求余,但这种方法特别慢,当b较大时无法使用。下面给出一种较快的算法(用A^b表示A的b次方):
  若b=0,则A^b%m=I%m。其中I表示单位矩阵。
  若b为偶数,则Ab%m=(A(b/2)%m)^2%m,即先把A乘b/2次方对m求余,然后再平方后对m求余。
  若b为奇数,则Ab%m=(A(b-1)%m)*a%m,即先求A乘b-1次方对m求余,然后再乘A后对m求余。
  这种方法速度较快,请使用这种方法计算A^b%m,其中A是一个2x2的矩阵,m不大于10000。

#include <iostream>
using namespace std;
int res[2][2];
int sum;
int b, m;
void mutil(int e[][2], int tmp[][2], int m)//计算矩阵相乘,并求出矩阵中每个数对m的求余
{
    int t[2][2];
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            sum = 0;
            for (int k = 0; k < 2; k++)
            {
                sum += e[i][k] * tmp[k][j];
            }
            t[i][j] = sum%m;
        }
    }
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            e[i][j] = t[i][j];
        }
    }
    return;
}
void runPow(int re[][2], int b, int m)
{
    if (b == 0)
    {
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                if (i == j) re[i][j] = 1%m;
                else re[i][j] = 0;
            }
        }
        return;
    }
    if (b % 2 == 1)//若b为奇数
    {
        int tmp[2][2];
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                tmp[i][j] = re[i][j];
            }
        }
        runPow(re, b - 1, m);
        mutil(re, tmp, m);
        return;
    }
    else//b为偶数
    {
        runPow(re, b / 2, m);
        mutil(re, re, m);
        return;
    }
    return;
}
int main()
{
    cin >> b >> m;
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            cin >> res[i][j];
        }
    }
    runPow(res, b, m);//计算矩阵乘方后的结果
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            cout<<res[i][j]<<" ";
        }
        cout << endl;
    }
    return 0;
}

45字符串编辑

解法:

46 S01串

解法:这是一个递归问题,当n=0时,输出为0,当n=1时,输出为1,当n>=2时,输出第n-2个字符,加第n-1个字符。

#include <iostream>
using namespace std;
string fun(int n);
int main()
{
    int n;
    cin >> n;
    cout << fun(n) << endl;
    return 0;
}
string fun(int n)
{
    if(n == 0)
        return "0";
    else if(n == 1)
        return "1";
    else
        return fun(n-2) + fun(n-1);
}


47 身份证排序

解法:希望按出生日期对它们进行从大到小排序,如果有相同日期,则按身份证号码从大到小进行排序。

使用结构体,一部分存储出生日期,一部分存储身份证号码。

#include<bits/stdc++.h>
using namespace std;

struct node{

	string id;
	string birth;

};
int cmp(struct node a,struct node b){
	if(a.birth!=b.birth)
		return a.birth>b.birth;
	else return a.id>b.id;


}
int main(){

	int n;
	while(cin>>n)
    {
        struct node number[n];

	int i;
	for(i=0;i<n;i++)
		{
			cin>>number[i].id;
			number[i].birth=number[i].id.substr(6,8);


		}
	sort(number,number+n,cmp);
	for(i=0;i<n;i++)
		{

			cout<<number[i].id<<endl;
		}
    }
	return 0;
}

48 回文数

解法:根据进制,算出颠倒数。两个数相加,若为回文数,则返回相加次数,若不是回文数,则继续相加,知道相加次数为30,若还不是回文数,则返回impossible.

#include <iostream>
#include <string>

using namespace std;

int radix, n, sum, flag, a[1001];//定义变量进制数,输入字符串长度,总步数,是否产生回文数,字符串存放的整数数组
string s;

//判断是否是回文数
bool palindromic(int n)
{
	for (int i = 1; i <= n / 2; i++)
		if (a[i] != a[n - i + 1])
			return false;
	return true;
}

//两数相加
int add(int n)
{
	int c[1001] = { 0 };//定义临时数组,表示两数的和
	for (int i = 1; i <= n; i++)//进制数相加
	{
		c[i] = a[i] + a[n - i + 1] + c[i];//使用同一个数组,进行求回文数
		c[i + 1] += c[i] / radix;
		c[i] %= radix;
	}
	if (c[n + 1])//保留进位
		n++;
	for (int i = n; i >= 1; i--)
	{
		a[i] = c[i];
	}
	return n;
}

int main()
{
    while(cin>>radix)
    {
        cin >> s;
	n = s.size();
	flag=1;
	for (int i = 1; i <= n; i++)//将字符串转化为整数数组
	{
		if (s[i - 1] < 65)
			a[i] = s[i - 1] - '0';
		else
			a[i] = s[i - 1] - 55;

	}
	while (sum <= 30)
	{
		if (palindromic(n))
		{
			cout << "STEP=" << sum << endl;
			flag=0;
			break;
		}
		sum++;
		n = add(n);
	}
	if(flag)
	cout << "Impossible!" << endl;
    }

	return 0;
}

50新生舞会

解法:使用结构体

#include <iostream>
#include <string>

using namespace std;

struct student
{
    string name;
    string num;
    char sex;
};


int main()
{
    int n;

    while(cin>>n)
    {
        struct student stu[n];
        for(int i=0;i<n;i++)
        {
           cin>>stu[i].name>>stu[i].num>>stu[i].sex;
        }
        int m;
        cin>>m;
        string inf1,inf2;
        char sex1,sex2;
        for(int j=0;j<m;j++)
        {
           cin>>inf1>>inf2;
        for(int i=0;i<n;i++)
        {
            //cout<<inf1<<inf2<<endl;
            if(stu[i].name==inf1||stu[i].num==inf1)
            {
                sex1=stu[i].sex;
                //cout<<inf1<<"sex1"<<sex1<<endl;
            }

            if(stu[i].name==inf2||stu[i].num==inf2)
            {
                sex2=stu[i].sex;
                //cout<<inf2<<"sex2"<<sex2<<endl;
            }


        }
        if(sex1==sex2)
            cout<<"N"<<endl;
            else
                cout<<"Y"<<endl;
        }
    }
}

51 班级排名

解法:使用结构体,获取每次的成绩,进行排名

52 铺地毯

解法:使用结构体存储坐标和长度信息,遍历结构体,找到覆盖给出节点的最大值,即为第几张地毯。

#include<cstdio>
#include<cstring>
struct node
{
	int a;
	int b;
	int c;
	int d;
}s[10010];
int main()
{
	int n,x,lx,y,ly,x1,y1;
	while(scanf("%d",&n)!=EOF)
	{
		memset(s,0,sizeof(s));
		for(int i=1;i<=n;i++)
		{
			scanf("%d %d %d %d",&x,&y,&lx,&ly);
			s[i].a=x;
			s[i].b=y;
			s[i].c=x+lx;
			s[i].d=y+ly;
		}
		scanf("%d %d",&x1,&y1);
		if(x1>100000 || y1>100000)
		{
			printf("-1\n");
			continue;
		}
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			if(s[i].a<=x1 && s[i].b<=y1 && s[i].c>=x1 && s[i].d>=y1)//满足给定的坐标点,落在已有的地毯上
			{
				ans=i;//因为地毯先后铺上,只要逐个遍历即可找到最上面的地毯
			}
		}
		if(ans)
			printf("%d\n",ans);
		else printf("-1\n");
	}
	return 0;
}

52 联系

解法:

53 最小乘积

解法:两组数分别相乘,求出最小值,那么只需要将两个数组进行排序,用一个数组的最大值乘于另外一个数组的最小值。

#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
    return a>b;
}
int main()
{
	int n;
	while(cin>>n)
    {
        while(n--)
        {
            int m;
        cin>>m;
        int num1[m];
        int num2[m];
        memset(num1,0,sizeof(num1));
        memset(num2,0,sizeof(num2));
        long long sum=0;
        for(int i=0;i<m;i++)
        {
            cin>>num1[i];
        }
        for(int i=0;i<m;i++)
            cin>>num2[i];
        sort(num1,num1+m);
        sort(num2,num2+m,cmp);
        for(int i=0;i<m;i++)
        {
            sum+=num1[i]*num2[i];
        }
        cout<<sum<<endl;
        }

    }
	return 0;
}


54 完美的代价

解法:1. impossible的情况:如果有一个字符出现的次数是奇数次数,而且n是偶数,那么不可能构成回文,如果n是奇数,但是已经有一个字符出现的次数是奇数次数了,那么如果又有一个字符是奇数次数,就不可能构成回文。

  1. 注意:若n是奇数,计算中间那个字符交换的次数的时候,不需要模拟把这个数移动到中间去,因为移动到中间的话——假设有一对数都在左边或者都在右边,那么交换成回文的时候就要经过中间,就会每次多加了1,而这个1是没有必要的,因为可以所有的回文移动完了之后再把这个独立的数移动过去,才能保证交换次数最少。
#include <bits/stdc++.h>
using namespace std;
char str[8005];
int main() {
    int n, r, ans = 0, temp = 0;
    scanf("%d%s", &n, str);
    r = n - 1;//r指向字符串需要交换的末尾下标
    for (int i = 0; i < n / 2; i++) {//i指针从头遍历到中间字符
        for (int j = r; j >= i; j--) {//j指针从后面往前一直到i寻找和str[i]相同的str[j]
            if (j != i) {
                if (str[i] == str[j]) {
                    for (int k = j; k < r; k++)//把str[j]换到str[r]处
                        swap(str[k], str[k + 1]);
                    ans += r - j;//统计交换次数
                    r--;//往前推进
                    break;
                }
            }
            else {//如果找不到相同的
                if (!(n & 1) || temp) {//impossible的两种情况, temp表示出现奇数次的字符。
                    printf("Impossible\n");//n&1,与运算,可以判断n是否为偶数,,如果是偶数,n&1返回0;否则返回1,为奇数。
                    return 0;
                }
                temp = 1;
                ans += n / 2 - i;//移动到中间需要的交换次数(距离即为交换次数),不需要现在交换过去,最后交换
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

56 纪念品分组

解法:进行排序,从小到大两端遍历,若和不大于给定的值,则次数加一,两端进位。若大于给定的值,只有大端进位,次数加一。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 30005;
int a[maxn];
int main ( )
{
    int w, n, ans = 0;
    cin>>w>>n;
    for ( int i = 0; i < n; i ++ )
        cin>>a[i];
    sort ( a, a+n ); //贪心
    for ( int i = 0, j = n-1; i <= j; )
    {
        if ( a[i]+a[j] <= w )   //要么取两个,要么就把最大的取了
            i ++, j --;
        else
            j --;
        ans ++;
    }
    cout<<ans<<endl;
    return 0;
}

57 旅行家的预算(难)

解法:思路:是找在最大行驶距离内寻找比当前便宜的加油站,然后判断是否能一次到达,不能的话先加满,然后一个一个判断直到剩下的油量不足到下一个加油站就加油,加适量。

于是有以下2 situations:

1.这个站点j 就是pos
  再细分两种情况:
    1.从pos就可以走到终点
      于是我们把油加到刚好到达终点即可
         cost += ((d[i] - d[pos]) / d2 - remain)*p[pos];就得到了最后答案。
         remain是当前剩余的油
    2.从pos不能一把走到终点
      于是,从当前位置走,走到哪里加油都不够在pos这里加油划算。
      所以加满。
2.这个站点j 是在pos后面的某个站点
  也有两种情况
    1.当前剩余的油remain不够走到j
      于是我们,把油加来刚好能够走到j就行了。(因为j这里好好便宜!)
    2.剩余的油remain足够,直接开过去就行了。

#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
double d[10000], p[10000];   //出发点每升汽油的价格p
int main()
{
	ios::sync_with_stdio(false);  //取消cin在stdin上的同步,增加cin的读取效率
	double d1, c, d2;
	int n;   //沿途油站数目
	cin >> d1 >> c >> d2 >> p[0] >> n;
	d[n + 1] = d1;   //第n个油站后即为最后的站点
	for (int i = 1; i <= n; i++)  //输入每一个油站离出发点的距离以及每个站点汽油的价格
	{
		cin >> d[i] >> p[i];
	}
	int pos = 0;
	double remain = 0, cost = 0;
	do
	{
		bool found = false;   //判定能不能到达
		for (int i = pos + 1; i <= n + 1 && d[i] <= d[pos] + c*d2; i++) //循环判断加满油能不能到达下一个加油站
		{
			if (p[i] < p[pos])   //判断下个站点汽油的价格是不是比这个pos站点汽油的价格小
			{
				if (d[pos] + remain*d2 >= d[i])  //若是剩余的油足够,刚好开过去
				{
					remain -= (d[i] - d[pos]) / d2;    //剩余的油减少,减少量就是从一个站点到下一个站点用到的油
				}
				else  //剩余的油不够
				{
					cost += ((d[i] - d[pos]) / d2 - remain)*p[pos];  //还需要加的油花费的价钱,不用加满
					remain = 0;   //到达下一个站点恰好没油了,所以剩余汽油量清0
				}
				pos = i;
				found = true;
				break;
			}
		}
		if (!found)
		{
			cost += (c - remain)*p[pos];  //不能到达前花费了多少钱
			remain = c - (d[pos + 1] - d[pos]) / d2;     //还剩多少油
			if (remain >= 0) pos++;  //小于0,油根本不够到达下一个站点,大于0,代表可以去下一个加油站
			else
			{
				cout << "No Solution";
				return 0;
			}
		}
	} while (pos <= n);  //循环条件:没到达终点
	cout.setf(ios::fixed);  //以定点形式显示浮点数
	cout << setprecision(2) << cost;
}

58 盾神与积木游戏

解法:要完成全部的作品,则每次要花最少的积木数,拼成尽可能的得到多的作品

这里用结构体设置三个字段:该孩子现有积木,拼成需要的积木,还差几个积木

要拼成尽可能多的作品,得到更多的积木,则需要将字段3由小到大的开始拼
对字段3进行升序排序,将每次剩余多少积木记录,判断,即可。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct node{
	int having;
	int need;//拼完一个积木作品所需的积木个数
	int mul;//差 = need - having
};

bool cmp(node a,node b){
	return a.mul<b.mul;//升序
}

int main()
{
	int m;
	int n;
	cin>>m;
	int having,need;

	for(int i=0;i<m;i++){
		cin>>n;
		vector<node>v;
		for(int j=0;j<n;j++){
			node a1;
			cin>>a1.having>>a1.need;
			a1.mul=a1.need-a1.having;
			v.push_back(a1);
		}

		sort(v.begin(),v.end(),cmp);//按照  need - having 的结果进行升序排序

		int rest=0;//剩余的积木数
		int flag=0;//够不够的标志
		for(int j=0;j<n;j++){
//			cout<<"rest="<<rest<<" "<<v[j].having<<","<<v[j].need<<","<<v[j].mul<<"  ";
			if(v[j].mul<=0){//积木数大于或等于,不用加积木,拼成功,推翻
				rest+=v[j].having;
			}else{
				rest-=v[j].mul;//扣掉积木给小朋友
				if(rest>=0){//积木数够
					rest+=v[j].need;//拼成功,推翻
				}else{//积木数不够直接退出
					flag=1;
					break;
				}
			}
		}
		if(flag==1)cout<<"NO"<<endl;
		else cout<<"YES"<<endl;
//		if(i<m-1) cout<<endl;
	}

	return 0;
}


60 瓷砖铺路

解法:使用递归,每次瓷砖加一或者加2,每次加到n,则次数累加,若大于n ,则不成功,返回

#include<iostream>
using namespace std;
int n;//瓷砖的长度
int ret = 0;//统计方案数
//递归
void dfs(int t){
   //如果当前层大于n,则退出
   if (t > n)
    return;
   //当前层等于n,计数
   if (t == n){
    ret++;
    return;
   }
   //递归+1的
   dfs(t + 1);
   //递归+2的
   dfs(t + 2);
}
int main()
{
   cin >> n;
   //从0开始递归
   dfs(0);
   cout << ret << endl;
   return 0;
}

61 求先序排列

解法:按照中序和后序的关系,每次输出先序排列的一个数

#include<bits/stdc++.h>
using namespace std;
void preOrder(string in, string post)
{
	if ((int)in.length() > 0)
	{
		char c = post[(int)post.length() - 1];
		cout << c;//每次输出先序排序的根节点
		int k = in.find(c);
		preOrder(in.substr(0, k), post.substr(0, k));//前部进行先序
		preOrder((in.substr(k + 1)), post.substr(k, post.length() - k - 1));//后部进行排序
	}
}
int main()
{
	string inOrder, postOrder;//中后
	cin >> inOrder >> postOrder;
	preOrder(inOrder, postOrder);
	cout<<endl;
	return 0;
}

62 FBI树

解法:进行深度优先遍历,按照后续遍历,先访问左子树,再访问右子树,再访问根节点

#include<bits/stdc++.h>
using namespace std;
char a[2500];
void FBI(int i,int j)
{
    int mid;
    int I,B;
    if (i<=j)
    {
        mid=(i+j)/2;
        I=0;
        B=0;
        if (i!=j)//先访问左子树,再访问右子树,再访问根节点
        {
            FBI(i,mid);//分出左子树
            FBI(mid+1,j);//分出右子树
        }
        for (int m=i; m<=j; m++)
            if (a[m]=='0') B++;
            else I++;
        if (B>0 && I>0) printf("F");
        else if (B) printf("B");
        else printf("I");
    }
}
int main()
{
    int n;
    cin>>n;
    cin>>a;
    FBI(0,pow(2,n)-1);
    return 0;
}

  • 4
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
XAUT OJ刷题答案 1004 选择结构习题:奇偶判断 65%(4810/7381) 38% 2020-4-23 1007 循环结构习题:输入两个整,输出它们的最大公约 66%(4379/6621) 36% 2020-4-23 1008 顺序结构习题:求三个的平均值 63%(4500/7162) 39% 2020-4-23 1009 顺序结构习题:求两点之间的距离 61%(4135/6812) 41% 2020-4-23 1010 顺序结构习题:摄氏温度转换为华氏温度和绝对温度 53%(3782/7194) 49% 2020-4-23 1011 选择结构习题:求三个的最大值 52%(4280/8171) 50% 2020-4-23 1012 循环结构习题:公式求π值 61%(3955/6500) 42% 2020-4-23 1013 循环结构习题:输入10个整 ,输出所有负并求其和 62%(3952/6347) 40% 2020-4-23 1014 循环结构习题:输出同构 50%(3855/7711) 52% 2020-4-23 1015 选择结构习题:百分值转换成其相应的等级 45%(3592/7997) 56% 2020-4-23 1017 循环结构习题:求一个分序列的值。 65%(3404/5227) 36% 2020-4-23 1018 循环结构习题:求2+22+222+....+22222的值 49%(3611/7443) 54% 2020-4-23 1019 循环结构习题:大小写字母转换 52%(3316/6343) 49% 2020-4-23 1020 循环结构习题:任意输入n个,输出最大和最小值及其对应的序列号 56%(3078/5455) 45% 2020-4-23 1021 选择结构习题:三个排序 66%(3470/5220) 35% 2020-4-23 1022 选择结构习题:分段函 33%(3464/10497) 68% 2020-4-22 1023 循环结构习题:打印“完” 73%(3105/4241) 28% 2020-4-23 1030 函习题(1):输出水仙花 64%(3463/5435) 38% 2020-4-23 1031 ----------------趣味题:柱状图排序 10%(47/491) 92% 2020-4-23 1032 函习题(2):输入年月日,输出是本年第几天 53%(2842/5315) 48% 2020-4-23 1033 组习题(1):求矩阵中最大元素值,并与同行对角线元素交换 42%(2674/6374) 59% 2020-4-23 1034 函习题(3):函实现求最大公约和最小公倍 78%(2933/3754) 23% 2020-4-23 1037 函习题(5):递归方法完成Fibonacci列前n项 70%(2766/3924) 31% 2020-4-23 1038 组习题(2):将2个升序组合并为一个升序组 65%(2243/3425) 35% 2020-4-23 1039 函习题(6):判断一个是否是回文 67%(2794/4195) 35% 2020-4-23 1040 函习题(7):递归完成x的n次方的计算 72%(2283/3178) 30% 2020-4-23 1041 组习题(3):完成十进制转成为二进制 71%(2795/3951) 30% 2020-4-23 1043 函习题(8):递归方法求n阶勒让德多项式的值 63%(1671/2652) 38% 2020-4-23 1044 函习题(9):分解一个整的所有素因子 71%(2321/3252) 29% 2020-4-23 1045 组习题(4):输出Fibonacci列的前n项 57%(2538/4476) 46% 2020-4-23 1046 组习题(5):组元素前移 74%(2556/3466) 28% 2020-4-23 1047 组习题(6):有序组中插入若干,仍保持有序 70%(2141/3048) 30% 2020-4-23 1048 函习题(10):递归方法求计算x-x2+x3-x4+…+(-1)n-1xn值 54%(1551/2850) 48% 2020-4-23 1049 组习题(7):电文加密 64%(2345/3656) 35% 2020-4-23 1050 结构体习题(1):输入n名学生学号、姓名、三门课成绩,计算平均分,输出排行榜 50%(1966/3931) 50% 2020-4-23 1051 ----------------趣味题:输入三个字符串,按由小到大的顺序输出 39%(84/214) 62% 2020-4-15 1052 共用体习题(1):统计单位n名职工计算机水平考试成绩 64%(1139/1790) 36% 2020-4-23 1053 枚举型习题(1):输入整输出其对应的颜色 74%(1028/1383) 25% 2020-4-23 1054 指针习题(1):升序排序 77%(1424/1861) 24% 2020-4-21 1055 指针习题(2):编写字符串连接函strcat() 71%(1245/1753) 29% 2020-4-22 1056 指针习题(3):编写测字符串长度函strlen() 85%(1183/1393) 15% 2020-4-22 1058 指针习题(4):猴子选大王 42%(572/1348) 59% 2020-4-22 1060 C++题目:定义一个圆类,输入圆半径,输出元的面积和周长 33%(259/784) 68% 2020-4-23 1061 C++题目:用于存放图书的栈类 45%(38/84) 55% 2019-12-16 1062 C++题目:利用重载求最小值 39%(104/267) 62% 2019-12-16 1063 C++题目:友元类计算两点间距离 62%(169/272) 38% 2020-4-17 1064 C++题目:补全复类 53%(10/19) 47% 2019-11-4 1065 顺序结构习题:交换变量值 74%(1476/1997) 27% 2020-4-23 1066 顺序结构习题:大小写字母转换 71%(1430/2009) 30% 2020-4-23 1067 C++题目:利用静态据成员计算总成绩 51%(104/203) 49% 2020-4-17 1068 C++题目:矩阵类运算符重载-加法 39%(14/36) 63% 2019-12-16 1069 测试题一 80%(1056/1326) 21% 2020-4-21 1070 测试题二 67%(851/1261) 34% 2020-4-23 1071 C++题目:派生类求面积 34%(14/41) 66% 2019-12-16 1072 C++题目:利用模板练习顺序循环队列 57%(21/37) 43% 2019-12-16 1073 选择结构习题:输入0~6的字,输出对应星期的英文。 57%(783/1371) 44% 2020-4-23 1075 选择结构习题:实现简单值运算 34%(711/2109) 69% 2020-4-23 1076 选择结构习题:根据月份、旅客订票张和票价按优惠率计算费用 29%(481/1656) 73% 2020-4-23 1077 选择结构习题:时间格式转换 28%(484/1741) 75% 2020-4-23 1078 循环结构习题:自然n的各位字之和 63%(637/1008) 39% 2020-4-23 1079 循环结构习题:求前n项的和 62%(583/937) 40% 2020-4-23 1080 循环结构习题:输出字菱形 55%(439/797) 46% 2020-4-23 1081 循环结构习题:下三角乘法口诀表 29%(443/1529) 72% 2020-4-23 1082 循环结构习题:求所有含6的整的和 58%(478/818) 44% 2020-4-23 1083 循环结构习题:求一个除以9的商等于它各位字的平方和 86%(497/575) 14% 2020-4-23 1084 循环结构习题:求最优方案 50%(419/844) 53% 2020-4-23 1085 函习题:计算公式s=1+1/(1+2)+1/(1+2+3)+…+1/(1+2+…+n)的值 78%(482/616) 23% 2020-4-23 1086 函习题:用函实现判断一个整是否能被n整除 68%(469/690) 34% 2020-4-23 1087 1091 结构体习题:通过学生学号查询学生 结构体习题:通过职工信息输出高于平均工资的职工信息及高于平均工资的职工人

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值