251225 算法2 期末练习

问题 A: A018蜜蜂路线

题目描述

一只蜜蜂在下图所示的数字蜂房上爬动,已知它只能从标号小的蜂房爬到标号大的相邻蜂房,现在问你:蜜蜂从蜂房 m 开始爬到蜂房 n,m<n,有多少种爬行路线?

输入

输入 m,n 的值

输出

爬行有多少种路线

样例输入 复制
1 14
样例输出 复制
377
#include<bits/stdc++.h>
using namespace std;

int dp[100];
int main(){
    int m,n;
    scanf("%d%d",&m,&n);
    dp[m + 1] = 1;
    dp[m + 2] = 2;
    dp[m + 3] = 1 + 2;

    for(int i = m + 3;i <= n;i++){
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    printf("%d\n",dp[n]);

}

问题 B: B006 俄罗斯套娃

题目描述

俄罗斯套娃大家应该都玩过。是一个按照大小顺序可以嵌套在一起的玩具。现在有一个被拆开的俄罗斯套娃摆到了你的好友面前,但是,要想把它重新变成一个娃娃,必须要满足这样的规则:
1.娃娃的大小必须是从小到大排列好的。
2.你每次只可以交换相邻的两个娃娃。
这样的规则使你的好友变得很烦躁,假设娃娃的个数为n,如果交换娃娃的次数超过n*(n - 1) / 2 - 1次,那么你的好友就会烧掉这些娃娃。但是她很珍惜这些娃娃。现在她向你询问,她是否不会烧掉这个俄罗斯套娃?

输入

一个整数n(n <= 1000)
接下来n个数Si,Si表示当前位置娃娃大小。(Si不一定小于n)。

输出

如果好友不会烧掉娃娃输出"YES"(没有引号),反之输出"NO"(没有引号)。

样例输入 复制
6
6 5 4 3 2 1
样例输出 复制
NO
#include<bits/stdc++.h>
using namespace std;
int arr[1005];
void swap(int arr[],int a,int b){
    int t = arr[a];
    arr[a] = arr[b];
    arr[b] = t;
}

int main(){
    int n;
    int cnt = 0;
    bool change = false;
    bool shao = false;
    scanf("%d",&n);
    for(int i = 0;i < n;i++){
        scanf("%d",&arr[i]);
    }

    for(int i = 0;i < n - 1;i++){
        for(int k = 0;k < n - i - 1;k++){
            if(arr[k] > arr[k + 1]){
                swap(arr,k,k + 1);
                change = true;
                cnt++;
                if(cnt > n * (n - 1) / 2 - 1){
                    shao = true;
                    break;
                }
            }
        }
        if(!change || shao)break;
    }

    if(!shao)printf("YES\n");
    else printf("NO\n");

}

问题 C: C001 字符串计数

题目描述

给出m个字符串,要求输出重复n次的字符串有几个。

输入

先给定一个N,N≤100000,接着输入N个字符串。

输出

对于每组测试数据,输出若干行,每行两个正整数,第一个数表示重复的次数,第二个数表示在此重复次数下有几种不同的字符串。

样例输入 复制
5
BBA
BBA
BEA
DEC
CCF
样例输出 复制
1 3
2 1
#include<bits/stdc++.h>
using namespace std;
string str[100005];
int times[100005] = {0};//名字不要用time,报错!!

int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        //输入
        for(int i = 0;i < n;i++){
            //一定用cin输入!!
            cin >> str[i];
        }
        //初始化time!!
        memset(times, 0,n*sizeof(int));
        //记录重复次数
        sort(str,str+n);
        int cnt = 1;
        for(int i = 1;i < n;i++){
            if(str[i] == str[i-1]){
                cnt++;
            }else{
                times[cnt]++;
                cnt = 1;
            }
        }
        times[cnt]++;//最后一个别忘!!
        //输出
        for(int i = 1;i <= n;i++){
            if(times[i])printf("%d %d\n",i,times[i]);
        }

    }

}

问题 D: D002 最长上升子序列

题目描述

一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... <iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8)。

你的任务,就是对于给定的序列,求出最长上升子序列的长度。

输入

输入有很多组,每组输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。

输出

输出每组的最长上升子序列的长度。

样例输入 复制
7
1 7 3 5 9 4 8
6
2 3 4 1 6 5
样例输出 复制
4
4
#include<bits/stdc++.h>
using namespace std;
int a[1005];
int dp[1005];

int main(){

    int n;
    while(scanf("%d",&n) != EOF){
        for(int i = 0;i < n;i++){
            scanf("%d",&a[i]);
        }
        fill(dp,dp+1005,1);

        for(int i = 1;i < n;i++){
            for(int k = i - 1;k >= 0;k--){
                if(a[i] > a[k]){
                    dp[i] = max(dp[i],dp[k] + 1);
                }
            }
        }

        printf("%d\n",dp[n - 1]);
    }



}

问题 E: E009 小木棒

题目描述

George有一些长度相等的木棒,他随意的将这些木棒切成长度最多是50的小木棒。麻烦来了,他现在想将这些杂乱的小木棒恢复到原来的木棒,但是他忘记了原来到木棒的数量和长度。请你帮助他设计一个程序计算出原来木棒可能的最小长度,所有小木棒的长度均表示为大于0的整数。

输入

每组输入数据包括两行。第一行是George切后小木棒的个数,最多有64根小木棒;第二行是这些小木棒的长度,这些长度表示为空格分开的整数。输入样例以整数0表示结束。

输出

输出一行,即为原始木棒可能的最小长度。

样例输入 复制
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
样例输出 复制
6
5
#include<bits/stdc++.h>
using namespace std;
int stick[65];
bool visited[65];
int n,lensum,res,avelen;
//剩余长度 拼好的*小木棒*数 当前使用的木棒下标
bool backtracking(int len,int ok_stick,int index){
    if(ok_stick == n)return true;
    //一根长木棒拼完了,重新从头遍历
    if(len == 0){
        len = avelen;//ok_stick指小木棒,不要在这加
        index = n;
    }
    //i-- i++写错
    for(int i = index - 1;i >= 0;i--){
        if(stick[i] > avelen)continue;
        if(!visited[i] && stick[i] <= len){
            visited[i] = true;
            if(backtracking(len - stick[i],ok_stick + 1,i))return true;
            visited[i] = false;
            //当前木棒不能拼出平均长度,之后也永远拼不进去
            if(len == avelen)return false;
        }
    }
    return false;


}

int main(){
    while(scanf("%d",&n) != EOF){
        if(n == 0)break;
        //输入
        lensum = 0;
        for(int i = 0;i < n;i++){
            scanf("%d",&stick[i]);
            lensum += stick[i];
        }
        //排序!!
        sort(stick,stick+n);
        res = lensum;//最大平均长度:所有木棒合成一根
        int min_stick = stick[0];
        for(int i = min_stick;i <= lensum / 2;i++){
            //平均长度保证整数
            if(lensum % i == 0){
                //初始化!!!
                fill(visited,visited+n,false);
                avelen = i;
                if(backtracking(avelen,0,n)){
                    res = i;
        
                    break;
                }
            }
        }
        printf("%d\n",res);

    }
}

问题 F: F008 排队买饭

题目描述

周晓晓吃完中午饭后又觉得没吃饱,因此想要再去食堂买点饭,当她走进食堂发现已经有n个人排队了,她知道每个人买饭需要的时间。她想帮助大家尽快的买到饭,即让n个人的平均等待时间最小,周晓晓已经饿的无法想出办法,只想知道他们最小的平均等待时间是多少,你能帮助她吗?

输入

输入可能有多组,每组第一行为一个整数n。 第二行 n 个整数,第 i 个整数 Ti 表示第i个人的等待时间Ti。

输出

每组输出占一行,为每组最小的平均等待时间(输出结果精确到小数点后两位)。

样例输入 复制
10 
56 12 1 99 1000 234 33 55 99 812
样例输出 复制
532.00
#include<bits/stdc++.h>
using namespace std;
double a[10000];
int main(){

    int n;
    while(scanf("%d",&n) != EOF){
        for(int i = 0;i < n;i++){
            scanf("%lf",&a[i]);
        }
        sort(a,a+n);
        double time = 0;
        for(int i = 0;i < n;i++){
            time += a[i] * (n - i);
        }
        double res = time / n;
        printf("%.2f\n",res);
    }

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值