• 牛客网


    [编程题]拜访

    现在有一个城市销售经理,需要从公司出发,去拜访市内的商家,已知他的位置以及商家的位置,但是由于城市道路交通的原因,他只能在左右中选择一个方向,在上下中选择一个方向,现在问他有多少种方案到达商家地址。

    给定一个地图map及它的长宽nm,其中1代表经理位置,2代表商家位置,-1代表不能经过的地区,0代表可以经过的地区,请返回方案数,保证一定存在合法路径。保证矩阵的长宽都小于等于10。

    测试样例:
    [[0,1,0],[2,0,0]],2,3
    返回:2
    class Visit {
    public:
        int countPath(vector<vector<int> > map, int n, int m) {
            // write code here
            int x1, y1, x2, y2;
            for(int i = 0; i < n; ++i)
                for(int j = 0; j < m; ++j)
                    if(map[i][j] == 1){x1 = i; y1 = j;}
                    else if(map[i][j] == 2){x2 = i; y2 = j;}
            int nx = std::abs(x1 - x2)+1;
            int ny = std::abs(y1 - y2)+1;
            vector<vector<int> > count(nx, vector<int>(ny, 0));
             
            count[0][0] = 1;
            for(int i = 1; i < nx; ++i)
                if(map[x1+((x2>x1)?i:-i)][y1] != -1)
                    count[i][0] = count[i-1][0];
            for(int i = 1; i < ny; ++i)
                if(map[x1][y1+((y2>y1)?i:-i)] != -1)
                    count[0][i] = count[0][i-1];
                 
            for(int i = 1; i < nx; ++i)
                for(int j = 1; j < ny; ++j)
                    if(map[x1+((x2>x1)?i:-i)][y2+((y2>y1)?j:-j)] != -1)
                        count[i][j] = count[i-1][j] + count[i][j-1];
                 
            return count[nx-1][ny-1];
        }
    };
    [编程题]旅途
    原来是要到醋溜站台乘坐醋溜快车到醋溜港”,亮亮解出了地图隐藏的秘密,赶紧奔向醋溜站台,但到了之后,亮亮忧桑地发现,从醋溜站台到醋溜港沿途的每个车 站都有很多美女被他飒爽的英姿所吸引,只要经过车站就会被这些漂亮的女孩搭讪,但是现在亮亮一心想要寻找楚楚街而没空去搭理她们,所以亮亮希望在抵达醋溜 港的时候被搭讪的次数最少。问亮亮抵达醋溜港最少会被搭讪多少次?

    输入描述:
    第一行包含两个整数N(2<=N<=5000),M(1<=M<=50000)。N表示公有N个汽车站,M表示公有M条公路,起点为1,终点为N。
    第二行包含N个整数(0<=K<=10000),第i个整数表示在第i站有K个美女想要搭讪亮亮。
    接下来M行,每行包含两个整数P(1<=P<=N),Q(1<=Q<=N),代表P,Q两个站是有班车直达的。


    输出描述:
    一个整数,即亮亮抵达醋溜港最少需要被搭讪的次数。

    输入例子:
    5 5
    0 1 1 3 6
    1 2
    1 4
    2 3
    3 5
    4 5

    输出例子:
    8
    #include<iostream>
    #include<vector>
    using namespace std;
    int Dijkstra(vector<vector<int>>& road, int N);
    int main()
    {
        int N, M;
        while (cin >> N >> M)
        {
            vector<int> station(N + 1);
            int Inf = 0x7fffffff;
            vector<vector<int>> road(N + 1, vector<int>(N + 1, Inf));
            for (int i = 1; i <= N; i++)
                cin >> station[i];
            for (int i = 0; i<M; i++)
            {
                int temp1, temp2;
                cin >> temp1 >> temp2;
                road[temp1][temp2] = station[temp2];   //1表示可以到达
                road[temp2][temp1] = station[temp1];
                road[temp1][temp1] = station[temp1];
                road[temp2][temp2] = station[temp2];
            }
            int res = Dijkstra(road, N);
            cout << res << endl;
        }
    }
    int Dijkstra(vector<vector<int>>& road, int N)
    {
        vector<bool> Mark(N + 1, true);
        int Inf = 0x7fffffff;
        vector<int> min(N + 1, Inf);
        int min_flag = Inf;
        int pos_flag;
        int start = 1;
        Mark[start] = false;
        //min[start] = road[start][start];
        for (int i = 2; i <= N; i++)
        {
            if(road[start][i]!=Inf)
                //min[i] = min[start]+road[start][i];
                min[i] =road[start][i];
            if (min[i]<min_flag)
            {
                min_flag = min[i];
                pos_flag = i;
            }
        }
        //以上初始化完成
        int flag = 0;
        //while (flag != N - 1)
        while (Mark[N])
        {
            min_flag = Inf;
            start = pos_flag;
            Mark[start] = false;
            for (int i = 2; i <= N; i++)
            {
                if (Mark[i] && road[start][i] != Inf)
                {
                    if (min[start] + road[start][i]<min[i])
                    {
                        min[i] = min[start] + road[start][i];
                          
                    }
                   
                }
                 if (Mark[i] &&min[i]<min_flag)
                    {
                        min_flag = min[i];
                        pos_flag = i;
                    }
                  
            }
            flag++;
        }
        return min[N]+road[1][1];
    }

    以上使用邻接矩阵表示的,用邻接表表示更加的节省内存。

    以下是邻接表的做法。

    #include <iostream>
    #include <vector>
    #include <set>
    #include <string.h>
    #include <algorithm>
    #include <limits>
    using namespace std;
     
    int main(){
        int N,M;
        while(cin>>N>>M){
            vector<int> dp(N+1);
            for(int i=1; i<=N; i++) dp[i] = numeric_limits<int>::max();
            vector<vector<int>> adj(N+1);
            set<int> visited;
            vector<int> w(N+1);       
            for(int i=1; i<=N; i++) cin>>w[i];
             
            dp[1] = w[1];
            for(int i=1; i<=M; i++){
                int p, q;
                cin>>p>>q;
                adj[p].push_back(q);
                adj[q].push_back(p);
            }
             
            // 初始化dp       
            for(int i=0; i<adj[1].size(); i++){
                dp[adj[1][i]] = dp[1] + w[adj[1][i]];
            }
             
            while(visited.find(N) == visited.end()){        
                           
                int u; // 找到下一个加入visited的点
                int temp = numeric_limits<int>::max();
                for(int j=1; j<=N; j++){
                    if(!visited.count(j) && dp[j] < temp){
                        temp = dp[j];
                        u = j;
                    }                  
                }
                visited.insert(u);
     
                // relax
                for(int k=0; k<adj[u].size(); k++){
                    if(dp[u]+w[adj[u][k]] < dp[adj[u][k]]){
                        dp[adj[u][k]] = dp[u]+w[adj[u][k]];
                    }
                }
            }      
            cout<<dp[N]<<endl;
        }
        return 0;
    }
    字符编码

    题目描述

    请设计一个算法,给一个字符串进行二进制编码,使得编码后字符串的长度最短。

    输入描述:
    每组数据一行,为待编码的字符串。保证字符串长度小于等于1000。


    输出描述:
    一行输出最短的编码后长度。

    输入例子:
    MT-TECH-TEAM

    输出例子:
    33
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #include<string.h>
    #define MAX 1000
     
    using namespace std;
     
    int main()
    {
        char newString[MAX] = {0};
       while(cin>>newString)
        {
            int i, j;
            int countNum = 0;     //统计不同字符个数
            int sum = 0;              //记录编码后的长度
            int first = 0, second = 0;      //分别记录队列的最小两个值
            int len = strlen(newString);
            priority_queue <int,vector<int>,greater<int> > huffmanQueue;   //定义小值优先级高的队列
             sort(&newString[0], &newString[len]);
         
             for(i = 0; i < len; )
             {
                     j = i;
                     while((j < len)&&(newString[j] == newString[i])) 
                    {
                          j++;
                    }
                   huffmanQueue.push(j - i);   //将字符newString[i]的个数压入队列
                    i = j;
                   countNum++;
            }
            for(i = 0; i < countNum - 1; i++)  //霍夫曼编码步骤
            {
                  first = huffmanQueue.top();
                  huffmanQueue.pop();
                  second = huffmanQueue.top();
                  huffmanQueue.pop();
                  huffmanQueue.push(first + second); 
                  sum += first + second;
            }
            cout<<sum<<endl;
        }//while
        return 0;
    }
    
       
    小米Git

    题目描述

    git是一种分布式代码管理工具,git通过树的形式记录文件的更改历史,比如: base'<--base<--A<--A' ^ | --- B<--B' 小米工程师常常需要寻找两个分支最近的分割点,即base.假设git 树是多叉树,请实现一个算法,计算git树上任意两点的最近分割点。 (假设git树节点数为n,用邻接矩阵的形式表示git树:字符串数组matrix包含n个字符串,每个字符串由字符'0'或'1'组成,长度为n。matrix[i][j]=='1'当且仅当git树种第i个和第j个节点有连接。节点0为git树的根节点。)
    输入例子:
    [01011,10100,01000,10000,10000],1,2

    输出例子:
    1
    class Solution {
    public:
        /**
         * 返回git树上两点的最近分割点
         *
         * @param matrix 接邻矩阵,表示git树,matrix[i][j] == '1' 当且仅当git树中第i个和第j个节点有连接,节点0为git树的跟节点
         * @param indexA 节点A的index
         * @param indexB 节点B的index
         * @return 整型
         */
         
    int getSplitNode(vector<string> matrix, int indexA, int indexB) {
        vector<bool> used(matrix.size(), false);
        vector<int> node_parent(matrix.size(),-1);
     
        queue<int> nums;
        nums.push(0);
        node_parent[0] = -1;
        used[0] = true;
        while (!nums.empty())
        {
            int size = nums.size();
            for (int i = 0; i < size; ++i)
            {
                int n = nums.front(); nums.pop();
                for (int j = 0; j < matrix[n].size(); ++j)
                {
                    if (matrix[n][j] == '1' && !used[j])
                    {
                        node_parent[j] = n;
                        used[j] = true;
                        nums.push(j);
                    }
                }
            }
        }
     
        vector<int> va;
        vector<int> vb;
        while (indexA != -1)
        {      
            va.push_back(indexA);
            indexA = node_parent[indexA];
        }
        while (indexB != -1)
        {
            vb.push_back(indexB);
            indexB = node_parent[indexB];
        }
        reverse(va.begin(),va.end());
        reverse(vb.begin(), vb.end());
        int idx = 0;
        for (int i = 0; i < min(va.size(), vb.size()) ; ++i)
        {
            if(va[i] == vb[i])
                idx = va[i];
            else
                break;
        }
        return idx;
    }   
             
    };
  • 相关阅读:
    BZOJ-1034: [ZJOI2008]泡泡堂BNB (田忌赛马贪心)
    BZOJ-2190: [SDOI2008]仪仗队 (欧拉函数)
    BZOJ-1864: [Zjoi2006]三色二叉树 (julao都说简单的树形DP)
    BZOJ-2657: [Zjoi2012]旅游(journey) (树形DP求最长链)
    BZOJ-2241: [SDOI2011]打地鼠 (模拟+枚举)
    BZOJ-1207: [HNOI2004]打鼹鼠 (LIS类似DP)
    BZOJ-1821: [JSOI2010]Group 部落划分 Group (二分+并查集)
    BZOJ-1218: [HNOI2003]激光炸弹 (前缀和+模拟)
    [SinGuLaRiTy] ZKW线段树
    [SinGuLaRiTy] 字节大小
  • 原文地址:https://www.cnblogs.com/qiaozhoulin/p/5796952.html
Copyright © 2020-2023  润新知