机试真题重点题目-2017

A:连续字母

#include <iostream>
#include <string.h>
#include <algorithm>

using namespace std;

const int N = 110;
int n;
char str[N];

int main()
{
    cin >> n;
    while(n --) {
        scanf("%s", str + 1);
        
        int cnt = 0, MAX = 0;
        int len = strlen(str + 1);
        
        cnt ++;//第一个字符一定算一个 
        
        for(int i = 2; i<=len; i++) {
            if(str[i] == str[i - 1]){
                cnt ++;
                MAX = max(cnt, MAX);
            }
            else{
                cnt = 1; //从不同字符处重新开始计,肯定也包括它 
            }
        }
        cout << MAX << endl;
    }
    return 0;    
}
/*
3
AAAABBCDHHH
ISDHFSHFDAASDIAHSD
EEEEEEE
输出:
4
2
7 
*/
View Code

B:疯狂的快递哥

考察:单源最短路径

Dijkstra解决:

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110, M = 10010, INF = 0x3f3f3f3f;
int n, m;//点,边
int g[N][N], dist[N];
bool st[N];
int pre[N]; //存储前驱结点 

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    for(int i = 0; i<n; i++) {
        int t = -1;
        for(int j = 1; j<=n; j++) {
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        st[t] = true;
        
        for(int j = 1; j<=n; j++) {
            if(dist[j] >= dist[t] + g[t][j])
                pre[j] = t;
            dist[j] = min(dist[j], dist[t] + g[t][j]);
        }
    }
    if(dist[n] == INF) return INF;
    else return dist[n];
}

void dfs(int u)
{
    if(u == 1) {
        cout << u << " ";
        return;
    }
    dfs(pre[u]);
    cout << u << " ";
}

int main()
{
    memset(g, 0x3f, sizeof g);
    cin >> n >> m;
    while(m --)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = g[b][a] = min(g[a][b], c);
    }
    
    //初始化前驱数组 
    for(int i = 1; i<=n; i++)
        pre[i] = i;
    
    int ans = dijkstra();
    dfs(n);
    
    return 0;
}
/*
5 6
1 2 1
2 3 5
3 4 5
3 5 10
1 3 2
4 5 4

输出:1 3 4 5

pre[n]:1 1 1 3 4 
*/
View Code

 

C:subrange_sum

与2019华为OD机试题类似,但华为是要求正整数,用滑动窗口解决,这里却有负数,似乎只能暴力解

华为OD版:

考察:滑动窗口

#include <iostream>

using namespace std;

const int N = 1000010;
int a[N];
int c, x;

int main()
{
    cin >> c >> x;
    for(int i = 0; i<c; i++) cin >> a[i]; 
    
    int l = 0, r = 0;
    long long count = 0;
    int sum = 0;
    
    while(r < c) {
        //从左边开始加 
        sum += a[r];
        while(sum >= x) { //只要sum大于x就符合要求,算作一个区间 
            if(sum >= x) {
                //当前sum已经大于x了,往后越大的数更成立 
                count += c - r;
            }
            sum -= a[l]; //保证区间是连续的,不会断开 
            l ++;
        }
        //当前sum不大于x时,r继续右移扩大区间 
        r ++;
    }
    cout << count << endl;
    return 0;
}
View Code

本题暴力版:

#include <iostream>

using namespace std;

const int N = 1000010;
int a[N];
int c, x;

int main()
{
    cin >> c >> x;
    int cnt = 0, sum = 0;
    
    for(int i = 0; i<c; i++) {
        cin >> a[i]; 
        if(a[i] >= x) //每个数自身就是一个区间 
            cnt ++;
    }
    
    for(int i = 0; i<c - 1; i++) {
        for(int j = i + 1; j<c; j++) {
            sum += a[i] + a[j];
            if(sum >= x) cnt ++;
        }
        sum = 0;
    }
    cout << cnt << endl;
    return 0;
}
View Code

 

D:进制转换

#include <iostream>

using namespace std;

long long x;

void Convert(int x, int n)
{
    if(n < 16)
    {
        if(x == 0) return;
        else {
            Convert(x / n, n);
            cout << x % n;
        }
    }
    else {
        if(x == 0) return;
        else {
            Convert(x / n, n);
            int re = x % n;
            if(re > 9) {
                char ch = re - 10 + 'A';
                cout << ch;
            } 
            else cout << re;
        }
    }
}

int main()
{
    cin >> x;
    Convert(x, 2);
    cout << endl;
    Convert(x, 8);
    cout << endl;
    Convert(x, 16);
    return 0;
}
View Code

 

E:疯狂的修路哥

考察:最小生成树

本题是用坐标形式给出的,可以先转换为点的编号,再用模板解决

#include <iostream>
#include <math.h>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10010;
const double INF = 1.0 / 0.0;
int n;

struct Point{
    int x, y, idx;
}points[N];

double g[N][N]; 
double dist[N] = {INF};
bool st[N];

double prim()
{
    for(int i = 1; i<=n; i++) dist[i] = INF;
    
    dist[1] = 0;
    double res = 0;
    
    for(int i = 0; i<n; i++) {
        int t = -1;
        for(int j = 1; j<=n; j++) {
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }
        st[t] = true;
        if(i && dist[t] == INF) return INF;
        if(i) res += dist[t];
        
        for(int j = 1; j<=n; j++)
            dist[j] = min(dist[j], g[t][j]);
    }
    return res;
}


int main()
{
    cin >> n;
    
    //初始化 浮点型不能用memset! 
    for(int i = 1; i<=n; i++)
        for(int j = 1; j<=n; j++) 
            g[i][j] = INF;

    
    for(int i = 1; i<=n; i++)
    {
        double x, y;
        cin >> x >> y;
        points[i].x = x, points[i].y = y;
        points[i].idx = i; //每个点的编号 
    }
    
    //计算距离
    for(int i = 1; i<=n; i++) {
        for(int j = 1; j<=n; j++) {
            double dx = points[i].x - points[j].x;
            double dy = points[i].y - points[j].y;
            double c = sqrt(dx * dx + dy * dy);
            int a, b;
            //将坐标转换为编号表示 
            a = points[i].idx, b = points[j].idx;
            cout << "a = " << a << " b = " << b << " c = " << c << endl;
            g[a][b] = g[b][a] = min(g[a][b], c);
            cout << "a = " << a << " b = " << b << " g[a][b] = " << g[a][b] << endl;
        }
    } 
         
    double res = prim();
    if(res == INF) cout << "impossible" << endl;
    else printf("%.2lf", res);
    return 0;
}
/*
4
0 0
100 0
0 1
1 100
输出:200.01 
*/
View Code

 

F:最长回文子序列

考察:动态规划

#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>

using namespace std;

const int N = 310;
char str[N];
int dp[N][N];

int main()
{
    cin >> str + 1;
    int len = strlen(str + 1);
    //统一转为小写字母
    for(int i = 1; i<=len; i++)
        if(str[i] >= 'A' && str[i] <= 'Z' )
            str[i] += 32; //A与a相差32 
            
    //初始化dp状态数组
    //dp[i][j]:str[i ~ j]的最长回文子序列长度
    for(int i = 1; i<=len; i++) dp[i][i] = 1;
    /*
    i <= j
    str[i] == str[j]时:dp[i][j] = dp[i+1][j-1] + 2,掐头去尾
    str[i] != str[j]时:dp[i][j] = max(dp[i+1][j], dp[i][j-1]); 
    计算dp[i][j]时要计算dp[i + 1][],即i处要用到i+1的数据,所以i要从大到小
    同理,j处要用到j-1的数据,故j要从小到大 
    */
    for(int i = len; i>=0; i--) {
        for(int j = i + 1; j<=len; j++) {
            if(str[i] == str[j])
                dp[i][j] = dp[i + 1][j - 1] + 2;
            else 
                dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);
        }
    } 
    cout << dp[1][len] << endl;
    return 0;
}
/*
ABCdca
输出:5 
*/
View Code

 

posted @ 2024-03-21 11:16  GeekDragon  阅读(4)  评论(0编辑  收藏  举报