【題目自解】北京大學2016計算機學科夏令營上機考試

【題目自解】北京大學2016計算機學科夏令營上機考試

A:分段函數(NOI 1.4編程基礎之邏輯表達式與條件分支)

解題思路ios

這題就像逗我玩似的,這連簡單題都算不上。c++

AC代碼編程

#include<cstdio>

using namespace std;

int main()
{
    double x, y;
    scanf("%lf", &x);
    if (x >= 0 && x < 5)y = 2.5 - x;
    else if (x >= 5 && x < 10)y = 2 - 1.5*(x - 3)*(x - 3);
    else if (x >= 10 && x < 20)y = x / 2 - 1.5;
    printf("%.3lf", y);
    return 0;
}

B:單詞翻轉(NOI 1.7編程基礎之字符串)

解題思路數組

簡單題,讀取一整行用C的gets()函數,VS2017沒有這個函數,Dev和OJ能夠過。app

AC代碼函數

#include<cstdio>
#include<cstring>
using namespace std;

int main()
{
    char s[505];
    gets(s);
    int len = strlen(s);
    for (int i = 0; i < len; i++)
    {
        if (s[i] == ' ')printf(" ");
        if (s[i] == '_')continue;
        else
        {
            int wlen = 0;
            int tmp = i;
            while (s[tmp] != ' ')
            {
                wlen++; tmp++;
                if (tmp >= len) break;
            }
            for (int j = i + wlen - 1; j >= i; j--)
            {
                printf("%c", s[j]);
                s[j] = '_';
            }
        }
    }
    return 0;
}

C:反反覆覆(NOI  1.8編程基礎之多維數組)

解題思路spa

簡單題,最基礎的二維數組。code

AC代碼blog

#include<cstdio>
#include<cstring>
int N[205][205];

int main()
{
    int m, n;//列和行 
    char s[205];
    scanf("%d", &m);
    scanf("%s", s);
    int len = strlen(s);
    n = len / m;
    int cnt = 1;
    for (int i = 0; i < n; i++)//按行讀入 
    {
        if (cnt % 2)//奇數行正向讀入
        {
            for (int j = 0; j < m; j++)N[i][j] = s[i*m + j];
            cnt++;
        }
        else//偶數行反向讀入
        {
            for (int j = m - 1; j >= 0; j--)N[i][m - 1 - j] = s[i*m + j];
            cnt++;
        }
    }
    for (int j = 0; j < m; j++)//按列輸出 
    {
        for (int i = 0; i < n; i++)printf("%c", N[i][j]);
    }
    return 0;
}

G:重建二叉樹

解題思路遞歸

詳細講解見二叉樹專題。核心思想其實很簡單,用數組就能夠直接作,無非就是根據前序遍歷的結果對中序遍歷左右子串分別遞歸,最後後序打印根節點的值。

AC代碼

#include<cstdio>
#include<cstring>
char s1[10000];//存儲前序
char s2[10000];//存儲中序

void f(int l, int l2, int r2)//老是須要前序遍歷的起點和中序遍歷的兩端,以肯定根結點和左右子樹
{
    if (l2 == r2)return;//沒有元素了
    char r = s1[l];//根結點
    int loc = l2;
    while (s2[loc] != r)loc++;//找到根結點在中序遍歷中的位置
    f(l + 1, l2, loc);
    f(l + loc + 1 - l2, loc + 1, r2);//畫一畫狀況就知道了
    printf("%c", r);
}

int main()
{
    while (scanf("%s%s", s1, s2) != EOF)
    {
        int len = strlen(s1);
        f(0, 0, len);
        printf("\n");
    }
    return 0;
}

H:叢林中的路

解題思路

中等題,最小生成樹的模板題。

AC代碼

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 30;
int p[N];//父結點,A表明編號0
int n, ans;//村落數目,最小開銷

struct Edge
{
    int a, b;
    int cost;
}edge[80];

bool cmp(Edge a, Edge b)
{
    return a.cost < b.cost;
}

void init()
{
    for (int i = 0; i < n; i++)p[i] = i;
    ans = 0;
}

int find(int x)
{
    return x == p[x] ? x : p[x] = find(p[x]);
}

void Union(int i)
{
    int a = find(edge[i].a);
    int b = find(edge[i].b);
    if (a == b)return;
    else
    {
        p[b] = a;
        ans += edge[i].cost;
    }
}

int main()
{
    int k, c, cnt;//與當前結點相連的村落數,和道路開銷,以及總道路數目
    char a[5], b[5];//兩結點名稱
    while (scanf("%d", &n) != EOF && n != 0)
    {
        cnt = 0;
        for (int i = 0; i < n - 1; i++)
        {
            scanf("%s%d", a, &k);
            for (int j = 0; j < k; j++)
            {
                scanf("%s%d", b, &c);
                edge[cnt].cost = c;
                edge[cnt].a = a[0] - 'A';
                edge[cnt].b = b[0] - 'A';
                cnt++;
            }
        }
        sort(edge, edge + cnt, cmp);
        init();
        for (int i = 0; i < cnt; i++) Union(i);
        printf("%d\n", ans);
    }
    return 0;
}

F:Dungeon Master

解題思路

三維地圖廣搜,算是廣搜的模板題了。寫出來就AC了,沒有什麼注意點。

AC代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int l, r, c;
char a[31][31][31];//存儲地圖
int vis[31][31][31];//訪問標記
int dx[6] = { 0,0,1,-1,0,0 };
int dy[6] = { 1,-1,0,0,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };

struct Node
{
    int z, x, y;//座標
    int t;//計時
    Node() :z(-1), x(-1), y(-1),t(0){}
    Node(int zz, int xx,int yy):z(zz), x(xx),y(yy),t(0){}
};

Node s, e;//起點和終點

bool noWay(int z,int x, int y)
{
    if (z < 0 || z >= l || x < 0 || x >= r || y < 0 || y >= c)return true;
    if (vis[z][x][y])return true;
    if (a[z][x][y] == '#')return true;
    return false;
}

void bfs()
{
    queue<Node> q;
    memset(vis, 0, sizeof(vis));
    q.push(s);//起點入隊
    vis[s.z][s.x][s.y] = 1;
    while (!q.empty())//開始廣搜
    {
        Node cur = q.front();
        if (cur.x == e.x&&cur.y == e.y&&cur.z == e.z)
        {
            printf("Escaped in %d minute(s).\n", cur.t);
            return;
        }
        q.pop();
        for (int i = 0; i < 6; i++)
        {
            int nz = cur.z + dz[i];
            int nx = cur.x + dx[i];
            int ny = cur.y + dy[i];
            if (noWay(nz, nx, ny))continue;
            Node next(nz, nx, ny);
            vis[nz][nx][ny] = 1;
            next.t = cur.t + 1;
            q.push(next);//入隊
        }
    }
    printf("Trapped!\n");
}

int main()
{
    while (scanf("%d%d%d", &l, &r, &c) != EOF && !(l == 0 && r == 0 && c == 0))
    {
        for (int k = 0; k < l; k++)
        {
            getchar();
            for (int i = 0; i < r; i++)
            {
                for (int j = 0; j < c; j++)
                {
                    scanf("%c", &a[k][i][j]);
                    if (a[k][i][j] == 'S')
                    {
                        s.z = k; s.x = i; s.y = j;
                    }
                    if (a[k][i][j] == 'E')
                    {
                        e.z = k; e.x = i; e.y = j;
                    }
                }
                getchar();//換行符
            }
        }
        bfs();
    }
    return 0;
}

D:文件結構「圖」

解題思路

以前的一道程設做業題,確實挺麻煩的,本身第一次作就WA了,大佬AC代碼以下。

AC代碼

#define TAB "|     "

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

using namespace std;

int cases=1;
char str[35];
bool isFinish=false;

void deal(int tab_num)
{
    string file_name[35];
    int file_num=0;
    scanf("%s",str);
    if (tab_num==0 && str[0]!='#')
    {
        if (cases>1)
            printf("\n");
        printf("DATA SET %d:\n",cases);
        printf("ROOT\n");
    }
    while (true)
    {
        if (str[0]=='*' || str[0]==']')
            break;
        else if (str[0]=='#')
        {
            isFinish=true;
            return;
        }
        else if (str[0]=='f')
            file_name[file_num++]=str;
        else if (str[0]=='d')
        {
            for (int i=0;i<tab_num+1;i++)
                printf("%s",TAB);
            printf("%s\n",str);
            deal(tab_num+1); 
        }
        scanf("%s",str);
    }
    sort(file_name,file_name+file_num);
    for (int i=0;i<file_num;i++)
    {   
        for (int j=0;j<tab_num;j++)
            printf("%s",TAB);
        printf("%s\n",file_name[i].c_str());
    }
    return;
}

int main()
{
    //freopen("output.txt","w",stdout);
    while (!isFinish)
    {
        deal(0);
        cases++;
    }
    return 0;
}
相關文章
相關標籤/搜索