2019网易笔试(1-3题)

本文探讨了三个算法问题:计算完成任务的最小代价、寻找到达目标位置的最少步数,以及翻转矩阵中牌面后的状态计数。通过具体示例和代码实现,展示了如何使用排序、动态规划和数学分析来解决这些挑战。

目录

 

1. 代价

2. 访友

3. 翻转翻转


1. 代价

你有3个需要完成的任务,完成这3个任务是需要付出代价的。
首先,你可以不花任何代价的完成一个任务;然后,在完成了第i个任务之后,你可以花费|Ai - Aj|的代价完成第j个任务。|x|代表x的绝对值。
计算出完成所有任务的最小代价。

输入描述:

一行3个整数A1,A2,A3,每个数字之间用一个空格分隔。所有数字都是整数,并且在[1,100]范围内。

 输出描述:

一个整数,代表最小的代价。

输入例子1:

1 6 3

输出例子1:

5

输入例子2:

10 10 10

 输出例子2:

0

思路:将数据排序,从最后一个开始,依次往前,累加当前任务和前一个的差即可。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    vector<int> data;
    int tmp, res = 0;

    for (size_t i = 0; i < 3; i++)
    {
        cin>>tmp;
        data.push_back(tmp);
    }

    sort(data.begin(),data.end()); //排序

    for (size_t i = data.size()-1; i >0; i--)
    {
        res += data[i] - data[i-1]; //从后往前依次累加差
    }
    
    cout<<res<<endl;

    return 0;
    
}

 

2. 访友

小易准备去拜访他的朋友,他的家在0点,但是他的朋友的家在x点(x > 0),均在一条坐标轴上。小易每一次可以向前走1,2,3,4或者5步。问小易最少走多少次可以到达他的朋友的家。

输入描述:

一行包含一个数字x(1 <= x <= 1000000),代表朋友家的位置。

输出描述:

一个整数,最少的步数。

输入例子1:

4

输出例子1:

1

输入例子2:

10

输出例子2:

2

思路一:一直往前走,每一步都迈最大的步子

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    
    int tmp, res = 0;
    int cur = 0, next = 0, jump = 0;
    int des;


    cin>>des;

    for (int i = 0; i <= des; i++)
    {
        if (cur<i) //还没有到达终点,最后一次是从des-1的地方开始走
        {
            jump++;   //向前走一步
            cur = next; //将从i-1能到达的最远的地方给cur
        }
        next = max(next, i+5); //从i出发能到达的最远的地方
        
    }

    cout<<jump<<endl;

    return 0;
    
}

思路二:简单求解,每一次都走5步,最后不够5步的加一次就好,只能针对这种特殊情况才能用。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
    
    int tmp, res = 0;
    int cur = 0, next = 0, jump = 0;
    int des;

    cin>>des;

    if (des%5 > 0)
    {
        jump = des/5+1;
    }else
    {
        jump = des/5;
    }
    
    cout<<jump<<endl;

    return 0;
    
}

 

3. 翻转翻转

 给定一个N*M的矩阵,在矩阵中每一块有一张牌,我们假定刚开始的时候所有牌的牌面向上。
现在对于每个块进行如下操作:
> 翻转某个块中的牌,并且与之相邻的其余八张牌也会被翻转。
XXX
XXX

XXX

如上矩阵所示,翻转中间那块时,这九块中的牌都会被翻转一次。
请输出在对矩阵中每一块进行如上操作以后,牌面向下的块的个数。

输入描述:

输入的第一行为测试用例数t(1 <= t <= 100000),
接下来t行,每行包含两个整数N,M(1 <= N, M <= 1,000,000,000)

输出描述:

对于每个用例输出包含一行,输出牌面向下的块的个数

输入例子1:

5
1 1
1 2
3 1
4 1
2 2

输出例子1:

1
0
1
2
0

思路一:分三种情况

1. 一行一列的只能翻一次,返回1

2. 1*m或n*1的情况一种,两头牌翻两次不变,中间的牌翻三次,向上变为向下,总的牌数减2即为结果

3. m*n的情况,4个角的牌被翻4次不变,4个边上除了角上的牌,会被翻6次也不变,中间的牌会被翻9次,向上变为向下,所以只要统计中间的牌有多少张就好,注意测试数据很大,需要用long long类型。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	long long num, N, M;
	vector<vector<long long>> data, data1;
	vector<long long> data_tmp, result;
	long long tmp, res = 0;



	cin>>num;

	for (int i=0;i<num;i++) //读数据
	{

		cin>>N>>M;
		data_tmp.push_back(N);
		data_tmp.push_back(M);
		data.push_back(data_tmp);
		data_tmp.clear();

	}

	for (int i=0;i<num;i++)
	{
		if (data[i][0] == 1 && data[i][1] == 1)    //1*1
		{
			result.push_back(1);
		}else if(data[i][0] == 1 || data[i][1] == 1){   //1*m或n*1
			result.push_back(max(data[i][0], data[i][1]) - 2);
		}else{                               //m*n
			result.push_back((data[i][0] - 2) * (data[i][1] - 2));
		}


	}

	for (int i=0;i<result.size();i++)
	{
		cout<<result[i]<<endl;
	}

	//cout<<result<<endl;

	return 0;

}

思路二:对每一张牌按照题目要求进行翻牌操作,在这里为了避免最外一层的牌需要判断边界的问题,在最开始的时候在最外层加一层牌,这样就避免了边界判断的问题。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main()
{
	int num, N, M;
	vector<vector<int>> data, data1;
	vector<int> data_tmp, result;
	int tmp, res = 0;



	cin>>num;

	for (int i=0;i<num;i++) //读数据
	{

		cin>>N>>M;
		data_tmp.push_back(N);
		data_tmp.push_back(M);
		data.push_back(data_tmp);
		data_tmp.clear();
		
	}

	for (int i=0;i<num;i++)
	{
		for (int j=0;j<data[i][1]+2;j++) //在最外层加上边界
		{
			data_tmp.push_back(0);
		}
		data1.push_back(data_tmp);
		data_tmp.clear();
		for (int j=0;j<data[i][0];j++)
		{
			data_tmp.push_back(0);
			for (int p=0;p<data[i][1];p++)
			{
				data_tmp.push_back(0);
			}
			data_tmp.push_back(0);
			data1.push_back(data_tmp);
			data_tmp.clear();
		}
		
		for (int j=0;j<data[i][1]+2;j++)
		{
			data_tmp.push_back(0);
		}
		data1.push_back(data_tmp);
		data_tmp.clear();


		for (int m=1; m<data[i][0]+1; m++) //对每一张牌进行翻牌操作
		{
			for (int n=1; n<data[i][1]+1; n++)
			{
				for (int p=-1;p<=1;p++)
				{
					for (int q=-1;q<=1;q++)
					{
						if (data1[m+p][n+q] == 0)
						{
							data1[m+p][n+q] = 1;
						}else{
							data1[m+p][n+q] = 0;
						}
					}
				}
			}
		}

		for (int m=1; m<data[i][0]+1; m++) //统计朝下的牌
		{
			for (int n=1; n<data[i][1]+1; n++)
			{
				if (data1[m][n] == 1)
				{
					res += 1;
				}
			}
		}

		result.push_back(res);
		res = 0;

		data1.clear();


	}

	for (int i=0;i<result.size();i++)
	{
		cout<<result[i]<<endl;
	}

	//cout<<result<<endl;

	return 0;

}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值