阿里巴巴(Alibaba)筆試編程題

前言

最近在牛客網上找了點阿里巴巴筆試的編程題做,現在做個簡單的總結。有的代碼還在調,會慢慢發出來。有的問題可以直接暴力破解的就不放出來了,一般那種問題幾層循環就解決了。不過筆試編程對時間和空間都有要求,有的題可能會過不了。如果題目本身比較有意義,我也會放到下面。

 

題目 1:

問題描述:小明在雙十一晚會上抽獎贏得了一次天貓超市免單的機會,享受在一個包裹內最大體積V,最大重量M內免單。假設商品i,體積Vi重量Mi庫存Si價格Pi目前天貓超市的商品分爲生鮮水產(1)、食品酒水(2)美妝個護(3)居家生活(4)四大類,且生鮮水產不與美妝個護同包裹請你幫助小明在購物車裏添置商品使得總價值最大 。

首先這個用例是錯誤的,我也是編完程才發現的。官方給的用例結果是33,很明顯就是第二種商品拿3個。但事實,要想達到最大價值,需要取第三種商品5個,再拿一個第二種商品,此時volume = 28wight = 30,value = 36符合要求

 

解題思路:剛開始時,我一直在糾結兩個物品不能同包裹這一條件,所以將問題想的太複雜了。後來發現,我完全可以創建 2 個vector,一個放水產和其他物品,另一個放美妝和其他物品。最後通過取兩種情況的最大價值便可以得到答案。通過上面的思路,將問題轉換成類似0-1揹包問題。

 

代碼如下:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

struct goods
{
	int wight;   //物品重量
	int volume;  //物品體積
	int value;   //物品價值
};

int goodssuma1 = 0, goodssuma2 = 0;      //用來記錄向量的長度
int Bagvolume,Bagwight,bestValue = 0;    //代表包裹的容量和能承受的重量
int Cvalue,Cwight,Cvolume;               //代表目前的價值,質量和容量
vector<goods> a1, a2;                    //a1放水產+其他商品,a2放美妝+其他商品


int Force(int i, const vector<goods> &x, int goodssum){
	if(i > goodssum-1)
	{
		if(bestValue < Cvalue && Cwight <= Bagwight && Cvolume <= Bagvolume)
			bestValue = Cvalue;
		return bestValue;
	}
	Cwight = Cwight + x[i].wight;                    //拿這件商品
	Cvalue = Cvalue + x[i].value;
	Cvolume = Cvolume + x[i].volume;
	if(Cwight <= Bagwight && Cvolume <= Bagvolume)   //超過任一要求就不需要再往下遞歸了
		Force(i+1, x, goodssum);

	Cwight = Cwight - x[i].wight;                    //不拿這件商品
	Cvalue = Cvalue - x[i].value;
	Cvolume = Cvolume - x[i].volume;
	if(Cwight <= Bagwight && Cvolume <= Bagvolume)
		Force(i+1, x, goodssum);

	return bestValue;
}

int main()
{
	int goodsnum,goodsvolume, goodswight, goodsn, goodsvalue, number, maxsum;
	goods asd;
	printf("物品種類、最大體積及最大重量:");
	scanf("%d,%d,%d", &goodsnum, &Bagvolume, &Bagwight);

	while(goodsnum--)
	{
		//商品輸入是:體積,重量,庫存,價錢 和 商品編號
		printf("輸入數據:");
		scanf("%d,%d,%d,%d,%d", &goodsvolume, &goodswight, &goodsn, &goodsvalue, &number);

		asd.wight = goodswight;
		asd.volume = goodsvolume;
		asd.value = goodsvalue;

		if(number == 1)
		{
			while(goodsn--)
				a1.push_back(asd);
		}
		else if(number == 3)
		{
			while(goodsn--)
				a2.push_back(asd);
		}
		else
		{
			while(goodsn--)
			{
				a1.push_back(asd);
				a2.push_back(asd);
			}
		}
		
	}
	
	goodssuma1 = a1.size();
	goodssuma2 = a2.size();

	int sum1 = Force(0, a1, goodssuma1);
	int sum2 = Force(0, a2, goodssuma2);
	if(sum1 > sum2)
		maxsum = sum1;
	else
		maxsum = sum2;

	printf("裝入最大總價值[%d]\n",maxsum);
	return 0;
}

 

題目 2:

問題描述:

有一個整數n,你需要經過若干次操作,使 n 不小於 m。可以對n完成以下操作:

操作1:將n變更爲 2*n ,花費爲w2;

操作2:將n變更爲 3*n ,花費爲w3。

當滿足n不小於m時,輸出最小花費。

 

輸入描述:

輸入第一行一個整數 T,代表測試 T 組數據。接下來 T 行,每行有4個整數,n, m, w2, w3。其中 1 <= T <= 10000, 1 <= n,m <= 2^(31) - 1, 1 <= w2,w3 <= 1000。

 

輸出:

對於每組數據,輸出一個整數代表最小花費。

input:
1  6  2  3
4  32 3  4
2  1  1  2
1  2147483647  1  4

output:
5
9
0
31

 

解題思路:這兩道題都是在求最優解,思路很相似,但是問題 2相對而言複雜一點。一方面是因爲原題題幹給的信息很難讀懂,另一方面原因是原題輸出的第二個示例答案給的是 8 ,正確答案應該是 9。這導致我開始沒有理解題目的意思,編程半小時,調試一整天,最後還得不到正確答案。當時人都崩潰了。發現不對後又開始重新看題,捋清楚題幹後總算是把題做出來了,第二道題就花了我 2 天時間(太難受了)。

 

代碼如下:

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

int w2,w3,Ccount = 0;
int bestcount = 999;
long n,m;

int asd(int i)
{
	if(i == 0 && n >= m)
		return 0;
	if(n < m)
	{
		n *= 2;
		Ccount = Ccount + w2;
		if(n >= m && bestcount > Ccount)
		{
			bestcount = Ccount;
			return bestcount;
			}
		else
			asd(i+1);

		n /= 2;
		Ccount = Ccount - w2;

		n *= 3;
		Ccount = Ccount + w3;
		if(n >= m && bestcount > Ccount)
		{
			bestcount = Ccount;
			return bestcount;
			}
		else
			asd(i+1);
			
		n /= 3;
		Ccount = Ccount - w3;
	}//if(n < m) end
	
	return bestcount;
}

int main()
{
	int times, value;
	cin >> times;

	while(times--)
	{
		cin >> n >> m >> w2 >> w3;
		value = asd(0);
		Ccount = 0;
		bestcount = 999;           //就是因爲忘了重置,讓我調試了半天
		cout << value <<endl;
	}	

	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章