牛客网

[编程题]拜访

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

给定一个地图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;
}   
         
};

 

posted @ 2016-08-22 20:46  linqiaozhou  阅读(487)  评论(0)    收藏  举报