今日头条2018校园招聘后端开发工程师(第三批)编程题 - 题解

[编程题] 编程题1

时间限制:1秒

空间限制:65536K

有一个推箱子的游戏, 一开始的情况如下图:

上图中, '.' 表示可到达的位置, '#' 表示不可到达的位置,其中 S 表示你起始的位置, 0表示初始箱子的位置, E表示预期箱子的位置,你可以走到箱子的上下左右任意一侧, 将箱子向另一侧推动。如下图将箱子向右推动一格;

..S0.. -> ...S0.

注意不能将箱子推动到'#'上, 也不能将箱子推出边界;

现在, 给你游戏的初始样子, 你需要输出最少几步能够完成游戏, 如果不能完成, 则输出-1。

输入描述:

第一行为2个数字,n, m, 表示游戏盘面大小有n 行m 列(5< n, m < 50);
后面为n行字符串,每行字符串有m字符, 表示游戏盘面;

输出描述:

一个数字,表示最少几步能完成游戏,如果不能,输出-1;

输入例子1:

3 6
.S#..E
.#.0..
......

输出例子1:

11

解题思路:经典问题推箱子,用bfs来解决,可用队列与优先队列都可以过。

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

const int N = 55;
char mp[N][N];
int vst[N][N][N][N];
int n,m;
int p_x,p_y,b_x,b_y,e_x,e_y;//代表人、箱、终点的X、Y

struct node{
    int p_x,p_y,b_x,b_y;
    int step_count;
    bool operator < (const node &rs)const{
		return step_count > rs.step_count ;//step大的优先级小 
	}
};

int dir[2][4] = {0,1,0,-1,
                 -1,0,1,0};

bool judge(int x,int y){
    if(x<0 || x>=n || y<0 || y>=m || mp[x][y]=='#')
        return false;
    else
        return true;
}

int bfs(node s){
    priority_queue<node> que;
    que.push(s);
    vst[s.p_x][s.p_y][s.b_x][s.b_y] = 1;
    
    while(!que.empty()){
        node cur = que.top();
        que.pop();
        if(cur.b_x==e_x && cur.b_y==e_y)
            return cur.step_count;
            
        for(int i=0;i<4;++i){
            int pxx = cur.p_x+dir[0][i];
            int pyy = cur.p_y+dir[1][i];
            int bxx = cur.b_x;
            int byy = cur.b_y;
            if(judge(pxx,pyy)){
                if(pxx==bxx && pyy==byy){
                    bxx += dir[0][i];
            		byy += dir[1][i];
                }
                if(!judge(bxx,byy))
                    continue;
                if(vst[pxx][pyy][bxx][byy])
                	continue;
                vst[pxx][pyy][bxx][byy] = 1;
                que.push(node{pxx,pyy,bxx,byy,cur.step_count+1});
            }
        }
    }
    return -1;
}

int main(){
    cin>>n>>m;
    
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            cin>>mp[i][j];
            if(mp[i][j] == 'S')
            {
                p_x = i;
                p_y = j;
            }
            else if(mp[i][j] == '0')
            {
                b_x = i;
                b_y = j;
            }
            else if(mp[i][j] == 'E')
            {
                e_x = i;
                e_y = j;
            }
        }
    }
    cout<<bfs(node{p_x,p_y,b_x,b_y,0})<<endl;
    
    return 0;
}

 

[编程题] 编程题2

时间限制:1秒

空间限制:65536K

有n个房间,现在i号房间里的人需要被重新分配,分配的规则是这样的:先让i号房间里的人全都出来,接下来按照 i+1, i+2, i+3, ... 的顺序依此往这些房间里放一个人,n号房间的的下一个房间是1号房间,直到所有的人都被重新分配。

现在告诉你分配完后每个房间的人数以及最后一个人被分配的房间号x,你需要求出分配前每个房间的人数。数据保证一定有解,若有多解输出任意一个解。

输入描述:

第一行两个整数n, x (2<=n<=10^5, 1<=x<=n),代表房间房间数量以及最后一个人被分配的房间号;
第二行n个整数 a_i(0<=a_i<=10^9) ,代表每个房间分配后的人数。

输出描述:

输出n个整数,代表每个房间分配前的人数。

输入例子1:

3 1
6 5 1

输出例子1:

4 4 4

思路:分配后的房间里,人数最少的那一个房间就是i号房间。如果有多个房间人数最少,则取x号房间往前数的第一个人最少的房间。综上:无论哪种情况,从x房间往前数找到的第一个人最少的房间就是i号房间。

 * 找出i号房间后,就很容易求出之前的人数了。首先根据i号房间最后的人数确定完整的轮数,然后从x号往前再减去最后不足一轮的部分,然后把多出的人数全部补到第i个房间,就结束了

注意:要用long long 类型保存,否则测试用例会超出范围

#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;

int main(){
	int n,x;
	cin>>n>>x;
	x = x-1;//为了匹配房间下标 
	vector<LL> vec(n);
	
	LL minval = 0x3f3f3f3f3f;
	for(int i=0;i<n;i++){
		cin>>vec[i];
		if(vec[i] < minval)
			minval = vec[i];
	}
	
	//找到最小下标i 
	int minIndex = x;
	while(vec[minIndex]!=minval){
		minIndex = (minIndex==0?n-1:minIndex-1);
	}
	
	// remove the round number.
	for(int i=0;i<n;i++)	
		vec[i] -= minval;
	
	// remove the tail	
	LL num = 0;
	for(int i = x;i!=minIndex;i = i==0?n-1:i-1){
		vec[i]--;
		num++;
	}
	vec[minIndex] = num + n*minval;
	
	for(int i=0;i<n;i++)
		cout<<vec[i]<<" ";

    
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值