• 北京大学程序设计实习2017年期末考试自解


    北京大学程序设计实习2017年期末考试自解

    1:蜜蜂

    一开始想用广搜,结果递归算法爆TLE了,这时候不得不抱dp的大腿,记忆化就是香。

    #include<iostream>
    #include<cstring> 
    using namespace std;
    long long int way[51];
    
    int main()
    {
        int T;
        cin >> T;
        while (T--)
        {
            int a, b;
            cin >> a >> b;
            memset(way, 0, sizeof(way));
            way[a + 1] = 1;
            way[a + 2] = 2;
            if (b <= a + 2)
            {
                cout << 1 << endl;
                continue;
            }
            for (int i = a+3; i <= b; i++)
            {
                way[i] = way[i - 2] + way[i - 1];
            }
            cout << way[b] << endl;
        }
        return 0;
    }
    第一题自解

    2:要变多少次

    想了半天字符串怎么操作,卡在字符串读取的终点怎么判定上,结果发现有个好东西叫strlen。

    看了大佬的代码,两点值得我学习,一是将字符串转为int数组,二是暴力破解的过程,高效直接。

    #include<iostream>
    #include<cstring>
    using namespace std;
    char str[1001];
    int s[1001];
    int l, num;
    void oper()
    {
        int sum;
        for (int i = 0; i <= l; i++)//i是第一个1出现的地方
        {
            sum = 0;
            for (int j = 0; j < i; j++)
                if (s[j] == 1)sum++;
            for (int j = i; j < l; j++)
                if (s[j] == 0)sum++;
            if (num > sum) num = sum;//暴力破解
        }
    }
    
    int main()
    {
        int T;
        cin >> T;
        while (T--)
        {
            cin >> str;//正序存储在str里面
            l = strlen(str);
            for (int i = 0; i < l; i++) s[i] = str[i] - '0';
            num = 1000;
            oper();
            cout << num << endl;
        }
        return 0;
    }
    第二题大佬题解

    3:未名冰场

    典型的深搜题,刚练过的城堡问题马上就用上了。

    #include<iostream>
    #include<cstring>
    using namespace std;
    int visited[101][101];//判定是否已访问过
    char map[101][101];//湖面
    int icePlaceNum;//结冰区域的数量
    int n, m;//map的总行数和列数
    void DFS(int x, int y)//对当前冰块进行深搜遍历
    {
        if (visited[x][y])return;//之前访问过该冰块
        visited[x][y] = 1;
        if (map[x][y + 1] == '@')DFS(x, y + 1);
        if (map[x][y - 1] == '@')DFS(x, y - 1);
        if (map[x + 1][y + 1] == '@')DFS(x + 1, y + 1);
        if (map[x + 1][y - 1] == '@')DFS(x + 1, y - 1);
        if (map[x - 1][y + 1] == '@')DFS(x - 1, y + 1);
        if (map[x - 1][y - 1] == '@')DFS(x - 1, y - 1);
        if (map[x + 1][y] == '@')DFS(x + 1, y);
        if (map[x - 1][y] == '@')DFS(x - 1, y);
    }
    
    int main()
    {
        int n, m;
        cin >> n >> m;
        while (n != 0 && m != 0)
        {
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                    cin >> map[i][j];
            icePlaceNum = 0;//结冰区域数清零
            memset(visited, 0, sizeof(visited));//visited数组清零
            for(int i=0;i<n;i++)
                for (int j = 0; j < m; j++)
                {
                    if (!visited[i][j] && map[i][j]=='@')//冰块没有被访问过
                    {
                        icePlaceNum++;
                        DFS(i, j);
                    }
                }
            cout << icePlaceNum << endl;
            cin >> n >> m;
        }
        return 0;
    }
    第三题自解

    4:迷阵

     不得不说这道题出得让我一点都不想帮主角过关...写了一个小时还是WA了,样例过了,应该是有些情况没考虑到。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    
    int m, n, H;
    int minStep = 1 << 30;
    char map[260][260];
    int visited[260][260];
    
    struct Node
    {
        int x, y;//坐标
        int h;//剩余血量
        int steps;//从起点到达该点所需步数
        Node(int xx, int yy, int step, int hh) :x(xx), y(yy), steps(step), h(hh){}
    };
    
    queue<Node> q;//构造队列
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
    
    bool check(Node tmp, int i)
    {
        if ((tmp.x + dx[i]) >= 0 && (tmp.x + dx[i]) < m && (tmp.y + dy[i]) >= 0 && (tmp.y + dy[i]) < n)//坐标合法
        {
            if ((map[tmp.x + dx[i]][tmp.y + dy[i]] == '*' && tmp.h <= 1)
                || map[tmp.x + dx[i]][tmp.y + dy[i]] == '#' 
                || visited[tmp.x + dx[i]][tmp.y + dy[i]]) return false;
            return true;
        }
        return false;
    }
    
    void bfs()//广搜
    {
        Node start(0, 0, 0, H);//初始化起始点
        visited[0][0] = 1;
        q.push(start);
        while (!q.empty())//广搜遍历地图
        {
            Node tmp = q.front();//读取队头元素
            q.pop();
            if (tmp.x == (m-1) && tmp.y == (n-1)) minStep = min(minStep, tmp.steps);
            for(int i = 0;i < 4; i++)
            {
                if (check(tmp, i))//检查下一点的坐标是否合法
                {
                    Node node(tmp.x + dx[i], tmp.y + dy[i], tmp.steps + 1, tmp.h);
                    if (map[tmp.x + dx[i]][tmp.y + dy[i]] == '*') node.h--;
                    q.push(node);
                    visited[tmp.x + dx[i]][tmp.y + dy[i]] = 1;
                }
            }
        }
    }
    
    int main()
    {
        int T;
        cin >> T;
        while (T--)
        {
            memset(visited, 0, sizeof(visited));
            minStep = 1 << 30;//重置最小步数
            cin >> m >> n >> H;//读入矩阵行列和血量
            for (int i = 0; i < m; i++)
                for (int j = 0; j < n; j++)
                    cin >> map[i][j];
            bfs();
            cout << minStep << endl;
        }
        return 0;
    }
    第四题自解WA代码

    又码了一遍大佬的代码,学习学习。不得不说大佬的代码太简洁了,整体思想和我的一致,但是简洁优美orz。

    #include<iostream>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    int m, n, H;
    char s[260][260];
    int visit[260][260];
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
    
    struct nodes
    {
        int x, y;
        int h;
        int T;
    };
    
    
    bool check(int a , int b)
    {
        if (a < 0 || a >= m || b < 0 || b >= n)return false;
        if (s[a][b] == '#') return false;
        return true;
    }
    
    int main()
    {
        int T;
        cin >> T;
        while (T--)
        {
            queue<nodes> q;
            memset(visit, 0, sizeof(visit));
            memset(s, 0, sizeof(s));
            int flag = 0;
            cin >> m >> n >> H;
            for (int i = 0; i < m; i++)cin >> s[i];
            nodes node0;
            node0.x = 0;
            node0.y = 0;
            node0.h = H;
            node0.T = 0;
            visit[0][0] = H - 1;
            q.push(node0);
            while (!q.empty())
            {
                nodes tmp = q.front();
                if (tmp.h <= visit[tmp.x][tmp.y])//执行了visited的功能,因为步数多的到达同一点没有更多的血量,和步数少的比就没有任何优势了
                {
                    q.pop();
                    continue;
                }
                visit[tmp.x][tmp.y] = tmp.h;
                for (int i = 0; i < 4; i++)
                {
                    int X = tmp.x + dx[i];
                    int Y = tmp.y + dy[i];
                    if (check(X, Y))
                    {
                        if (X == m - 1 && Y == n - 1)
                        {
                            cout << tmp.T + 1 << endl;
                            flag = 1;
                            break;
                        }
                        nodes node;
                        node.h = tmp.h;
                        if (s[X][Y] == '*')node.h--;
                        if (node.h == 0)continue;//不入队列
                        node.x = X;
                        node.y = Y;
                        node.T = tmp.T + 1;
                        q.push(node);
                    }
                }
                if (flag)break;
                q.pop();
            }
        }
        return 0;
    }
    大佬代码
  • 相关阅读:
    Excel Sheet Column Title&&Excel Sheet Column Number
    Trapping Rain Water——经典的双边扫描问题
    Rotate List
    图像处理---《读写图像、读写像素、修改像素值----反色处理》
    图像处理---《Mat对象 与 IplImage对象》
    图像处理---《计算 处理过程 的耗时》
    图像处理---《获取图像的像素指针、像素范围的处理、掩膜应用》
    图像处理---《对一张图片进行简单读入、修改、保存图像》
    图像处理---《搭一个基本框架》
    图像处理---《读取图像后“是否读入成功”的几种提示》
  • 原文地址:https://www.cnblogs.com/yun-an/p/11055805.html
Copyright © 2020-2023  润新知