2019 中南大学研究生招生夏令营机试题(1110~1114)

目录:

A:地砖问题 简单bfs
B:最小花费 dfs+dijkstra
C:回文串 动态规划
D:有序合并 数组排序
E:十六进制转换 字符串问题

A:地砖问题

http://39.106.164.46/problem.php?id=1110
题意:
求可以走过最多的黑砖个数。
思路:
简单的bfs。
AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 30
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,m;//n行,m列
char ch[MAX][MAX];
int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}},visit[MAX][MAX];

struct node{
    int x,y;
    node(int xx,int yy){
        x=xx;
        y=yy;
    }
};

bool judge(int x,int y){
    if(x<0||x>n-1||y<0||y>m-1) return false;
    return true;
}

int bfs(int x,int y){
    int sum=0;
    queue<node> q;
    node t(x,y);
    q.push(t);
    visit[x][y]=1;
    while(!q.empty()){
        node top=q.front();
        q.pop();
        int x=top.x;
        int y=top.y;
        if(ch[x][y]=='@'||ch[x][y]=='.') sum++;
        for(int i=0;i<4;i++){
            int xx=x+dir[i][0];
            int yy=y+dir[i][1];
            if(judge(xx,yy)&&visit[xx][yy]==0&&ch[xx][yy]=='.'){
                node tmp(xx,yy);
                visit[xx][yy]=1;
                q.push(tmp);
            }
        }
    }
    return sum;
}

int main(){
    while(scanf("%d %d",&m,&n)!=EOF){
        if(n==0&&m==0) return 0;
        memset(visit,0,sizeof(visit));
        for(int i=0;i<n;i++){
            scanf("%s",&ch[i]);
        }
        int x,y;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(ch[i][j]=='@'){
                    x=i,y=j;
                }
            }
        }
        int res=bfs(x,y);
        printf("%d\n",res);
    }
    return 0;
}

B:最小花费

http://39.106.164.46/problem.php?id=1111
题意:
Dijkstra + DFS模板题。
题目的意思其实是只能沿着一条路径转账,那么从A到B,我们可以找出所有的最短路径,一次dijkstra即可,在路径花费最小的情况下,可以再用一次dfs找出路径数量最多的那一条路径,这样就能保证损失的钱最少,那么A转给B的钱也就是最少的。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 2005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,m;
int mp[MAX][MAX],dis[MAX],vis[MAX];
vector<int> pre[MAX];
vector<int> path,tmppath;
int start,goal,ans=-1;

void dijkstra(int s){
    for(int i=0;i<=n;i++){
        vis[i]=0;
        dis[i]=INF;
    }
    dis[s]=0;
    for(int i=0;i<n;i++){
        int u=-1,minl=INF;
        for(int j=1;j<=n;j++){
            if(dis[j]<minl&&vis[j]==0){
                minl=dis[j];
                u=j;
            }
        }
        if(u==-1) break;
        vis[u]=1;
        for(int v=1;v<=n;v++){
            if(vis[v]==0&&mp[u][v]!=INF){
                if(dis[v]>dis[u]+mp[u][v]){
                    dis[v]=dis[u]+mp[u][v];
                    pre[v].clear();
                    pre[v].push_back(u);
                }else if(dis[v]==dis[u]+mp[u][v]){
                    pre[v].push_back(u);
                }
            }
        }
    }
}

void dfs(int v){
    tmppath.push_back(v);
    if(v==start){//当最短距离相同时,选择路径最多的一条
        int tmp=tmppath.size();
        if(ans<tmp){
            ans=tmp;
            path=tmppath;
        }
        tmppath.pop_back();
        return;
    }

    for(int i=0;i<pre[v].size();i++){
        dfs(pre[v][i]);
    }
    tmppath.pop_back();
}


int main(){
    while(scanf("%d %d",&n,&m)!=EOF){
        for(int i=0;i<MAX;i++){//初始化
            for(int j=0;j<MAX;j++){
                mp[i][j]=INF;
            }
        }
        int a,b,len;
        for(int i=0;i<m;i++){
            scanf("%d %d %d",&a,&b,&len);
            mp[a][b]=mp[b][a]=len;
        }
        scanf("%d %d",&start,&goal);
        dijkstra(start);
        ans=-1;
        dfs(goal);
        double res=100.0;
        int now=path[0];
        for(int i=1;i<path.size();i++){
            int rate=mp[now][path[i]];
            double r=(double)rate/100;
            res=res/(1.0-r);
            now=path[i];
        }
        printf("%.8lf\n",res);

    }
    return 0;
}

C: 回文串

http://39.106.164.46/problem.php?id=1112
思路:
其实就是简单的动态规划。枚举子串的长度即可。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

string s;
int dp[MAX][MAX];

int main(){
    while(cin>>s){
        memset(dp,0,sizeof(dp));//初始化
        int len=s.length(),ans=0;//ans记录总的连续回文子串个数
        for(int i=0;i<len;i++){
            dp[i][i]=1;
            ans++;
            if(i<len-1){
                if(s[i]==s[i+1]){
                    ans++;
                    dp[i][i+1]=1;
                }
            }
        }
        //状态转移方程
        for(int l=3;l<=len;l++){//枚举子串的长度
            for(int i=0;i+l-1<len;i++){
                int j=i+l-1;
                if(s[i]==s[j]&&dp[i+1][j-1]==1){
                    ans++;
                    dp[i][j]=1;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

D: 有序合并

http://39.106.164.46/problem.php?id=1113
思路:
注意读数的方式,用一个数组存储读进来的两行数,然后排序输出即可。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

int n,m;
vector<int> vec;
int num,cnt=0;

int main(){
    while(scanf("%d",&n)!=EOF){
        cnt++;
        for(int i=0;i<n;i++){
            scanf("%d",&num);
            vec.push_back(num);
        }
        if(cnt==2){
            sort(vec.begin(),vec.end());
            for(int i=0;i<vec.size();i++){
                printf("%s%d",i==0?"":" ",vec[i]);
            }
            cout<<endl;
            vec.clear();
            cnt=0;
        }
    }
    return 0;
}

E: 十六进制转换

http://39.106.164.46/problem.php?id=1114
思路:
将一个不超过100000位的十六进制数,转换成八进制数。使用map,首先可以将十六进制数转化为二进制数,然后补充前导0至长度为3的倍数,然后将这个二进制数转化为八进制数,最后不输出前导0即可。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 5005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;

string s;
map<char,string> mp1;
map<string,char> mp2;

int main(){
    mp1['0']="0000";mp1['1']="0001";mp1['2']="0010";mp1['3']="0011";
    mp1['4']="0100";mp1['5']="0101";mp1['6']="0110";mp1['7']="0111";
    mp1['8']="1000";mp1['9']="1001";mp1['A']="1010";mp1['B']="1011";
    mp1['C']="1100";mp1['D']="1101";mp1['E']="1110";mp1['F']="1111";

    mp2["000"]='0';mp2["001"]='1';mp2["010"]='2';mp2["011"]='3';
    mp2["100"]='4';mp2["101"]='5';mp2["110"]='6';mp2["111"]='7';
    while(cin>>s){
        string res="",tmp="";
        int len=s.length();
        for(int i=0;i<len;i++){
            tmp+=mp1[s[i]];
        }
        if(tmp.size()%3==1){//若余1,这说明差2位,前面补2个0,补成3的倍数
            tmp="00"+tmp;
        }else if(tmp.size()%3==2){//若余2,这说明差1位,前面补1个0
            tmp="0"+tmp;
        }
        for(int i=0;i<tmp.size();i+=3){
            res=res+mp2[tmp.substr(i,3)];
        }
        int flag=0;
        for(int i=0;i<res.size();i++){
            if(res[i]=='0'&&flag==0) continue;
            flag=1;
            cout<<res[i];
        }
        cout<<endl;
    }
    return 0;
}

你可能感兴趣的:(机试)